Basomti Kombucha Basomti Kombucha - 3 months ago 11
Javascript Question

Could somebody explain to me what exactly is happening in the Dojo's ''dojo/on" module?

I started fiddling around with Dojo.js and came across a thing I don't understand.

I'm trying to create my own widget. The widget would be really simple - it would just query all images on the page and make them listen for a 'click' event. Each click would increase the widget's counter attribute by 1.

Here's my take on it:

define(
[
"dojo/_base/declare",
"dojo/query",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dojo/text!myProject/folder/myWidgetTemplate.html",
],
function(declare, query, _WidgetBase, _TemplatedMixin, template) {
declare("MyWidget", [_WidgetBase, _TemplatedMixin], {

templateString: template,
counter: 0,

onClick: function(evt) {
this.counter++;
console.log(this.counter);
},

postCreate: function() {
query("img").on("click", this.onClick);
}

});
}
);


The widget initializes and I indeed can click on images, but the console always returns undefined.
It seems that I'm missing some core aspect about how the dojo/on module works. Could somebody explain to me what exactly happens in my code?

Answer

In your case, this is pointing to the image, and the property counter is undefined. to accomplish this, you can use the dojo/base/lang module

define(
    [                   
        "dojo/_base/declare",
        "dojo/_base/lang", //add this
        "dojo/query",
        "dijit/_WidgetBase",
        "dijit/_TemplatedMixin",
        "dojo/text!myProject/folder/myWidgetTemplate.html",
    ],
    function(declare, lang, query, _WidgetBase, _TemplatedMixin, template) {
        declare("MyWidget", [_WidgetBase, _TemplatedMixin], {

            templateString: template,
            counter: 0,

            onClick: function(evt) {
                this.counter++;
                console.log(this.counter);
            },

            postCreate: function() {
                //lang.hitch will return a new function with scope changed
                query("img").on("click", lang.hitch(this, this.onClick));
            }

        });
    }
);

lang.hitch will return a new function with the scope changed, so when you use this it will be pointing to the want you passed

You can avoid having to use lang by declaring the event in the html, for example

<img src="myImage.jpg" data-dojo-attach-event="onClick: onClick"/>  

Where onClick: onClick can be read as event: functionName, and functionName must exist in your widget.

Note that you can do the same using the native bind function of JavaScript by just doing

query("img").on("click", this.onClick.bind(this));

You can checkout this answer access this on external callback it is not about dojo but Javascript in general.