Reputation: 1115
I have a Dojo widget that looks as follows:
define([
// stuff...
], function(declare, lang, win, on, query,
_WidgetBase, _TemplatedMixin, _OnDijitClickMixin, template){
return declare("Toolbar", [_WidgetBase, _TemplatedMixin, _OnDijitClickMixin], {
templateString: template,
map: null,
constructor: function(options) {
// this.map set here
lang.mixin(this, options);
if (this.map === null) {
console.log("Error: no map!");
}
},
postCreate: function() {
on(this.domNode, ".toolButton:click", this.loadTool);
},
// in the following function, this refers to element where event
// originated here
loadTool: function(e) {
var clickedTool = "tools/Tool" + this.id[this.id.length - 1];
require([clickedTool], function(Tool) {
// Fails: want this.map to refer to map defined by constructor above
(new Tool({ map: this.map })).placeAt(win.body());
});
}
});
});
At the moment, this Toolbar
widget is just an ordered list of buttons, each having class toolButton
. When a button is clicked, it will conditionally load the module (which returns another widget) associated to the clicked button. For simplicity, the tool modules are named tools/Tool<some_number>
where <some_number>
is obtained from the id
on the clicked button.
I need to pass the map
property of the Toolbar
widget into the constructor of the Tool
widget as seen on this line:
(new Tool({ map: this.map })).placeAt(win.body());
However, as noted above, within loadTool
, this
refers to the button that was clicked and not to the Toolbar
widget. One possibility would be to called the event listener as
on(this.domNode, ".toolButton:clicked", lang.hitch(this, this.loadTool);
and then obtain the id
of the clicked button from the event object...but this seems hacky and like the incorrect way to handle it.
What is the "best practice" for doing this?
Upvotes: 1
Views: 279
Reputation: 2604
The best practice is to pass the context to the callback function, like your second approach. This allows you to control how a function executes, particularly in asynchronous operations.
From dojo documentation:
on(something, "click", processEvent);
In asynchronous callbacks such as above, the context that the code is executing in has changed. It will no longer refer to the object that originally provided it, but its context will now refer to the enclosing object, the callback. To get around this, you can use hitch() to force the function to retain its original context.
The same code done properly will look like:
on(something, "click", lang.hitch(this, processEvent));
http://dojotoolkit.org/reference-guide/1.10/dojo/_base/lang.html#dojo-base-lang-hitch
Upvotes: 1