dojoAttachEvent: what it's for and how to use it
Level: Intermediate
Date: Originally
posted 3/08, updated 4/08.
Author: Richard Bondi,

This post explains what the dojoAttachEvent attribute is for in a Dojo widget. You should already know how to create a
Dojo widget, and how Dojo loads declarative widgets.
The Problem
You've written a widget, and you want other programmers to be able to change how it responds to events without forcing them to have to edit your existing event code. (In other words, you want your widget's event handling to be extensible without being modifiable.)
The Solution
To explain the solution, we need to distinguish carefully between DOM events and widget events. There are two important differences.
First, the browser has hard-wired DOM events to DOM nodes for you: they just happen. So if a user clicks on a <div>, an "onclick" fires; specifically, a function "onblur" of the <div> is called. You don't have to do anything to make that happen.
Widget events are not hard-wired by the browser. They are methods the widget author has to write, and somehow they have to be called when a DOM event fires. These widget methods aren't really "events" in the DOM sense. They are plain old Javascript functions/methods that you write, but which can be wired up to DOM events. Nevertheless, everyone calls them "widget events".
Second, it is helpful to be aware of the difference between the active area of a DOM event and of a widget event. A widget may contain many DOM elements, each of whose "onblur" events fire as you move the mouse over and out of them. But when the mouse moves outside the widget's boundary, you would want a custom function, perhaps called _onBlur, to fire.
Dojo provides a declarative way to attach any widget method to a DOM event, in the sense that when the DOM event fires, the widget method will be called. The widget author can use this to wire up DOM events and widget methods. Together with a dojo convention called an "extension point" this technique can also be used to add or override widget methods with your own, without having to touch the widget's Javascript source code -- in short, to extend the widget without modifying it. This is accomplished in three steps, detailed below.
Step 1
In your widget's template html, add the attribute dojoAttachEvent to any html tags whose events should call widget events. The dojoAttacheEvent attribute's value should be the name of a DOM event, a colon, and the name of a plain old Javascript method in your widget's .js file. The attribute value can contain a comma separated list of such DOM event - Javascript method pairs.
This code fragment from dijit.form.Button's Button.html template file contains an example of three "attached" events.
[File:Button.html]
<div class="dijit dijitLeft dijitInline dijitButton"
dojoAttachEvent="onclick:_onButtonClick,onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse"
> ...
Note the part in red. The
onclick refers to the DOM event on this div. The
_onButtonClick refers to a plain old Javascript method in Button.js.
Step 2
In your widget's Javascript file, define the plain old Javascript method in dojoAttachEvent, as well as an "extension point" method (defined below) for your programmer to override.
Once again, let's see how this is done in the dijit.form.Button widget, in Button.js. An ellipsis (...) indicates code that I have not typed in.
[File:Button.js]
_onButtonClick: function( /*Event*/ e) {
... // I haven't retyped the actual code. Trust me, _onButtonClick calls this._onClick below.
},
_onClick: function( /*Event*/ e) {
...
return this.onClick(e); // And here this._onClick calls this.onClick.
},
onClick: function(/*Event*/ e) { // nothing here: this method is the extension point! You can pass in any parameters and just use this.arguments to get at them.
;
}
Here is what this code is going on.
The code in Step 1 causes all DOM "onclick" events to be redirected to the Button widget's plain old Javascript method _onButtonClick.
_onButtonClick does things that are intrinsic to the Button widget, and must always happen; then it calls _onClick.
_onClick does things that must always happen, and then calls onClick.
onClick does nothing! It's empty!
Why? Because it is here that the programmer can add their own function, for some custom action that should happen every time the DOM event onclick fires. This empty function is called an "extension point".
Step 3 shows how the widget user can add their custom function to the extension point, thus adding event functionality without modifying the widget Javascript source code.
Step 3
In some html page that is using (dojo.require-ing) the dijit.form.Button widget, the user writes this:
[File: any html file using dijit.form.Button]
<div dojoType="dijit.form.Button">
<script type="dojo/method" event="onClick" args="evt">
alert('Woohoo! I'm using the extension point "onClick"!!');
</script>
</div>
Now, whenever someone in the browser clicks on the Button widget (specifically inside it's top-level div in this case), _onButtonClick and _onClick will execute, but so will the extra alert() statement.
Note carefully what we set the "event" attribute to: we did NOT set it to "onclick" (the DOM event) or to the two required Button.js methods (_onButtonClick and _onClick), but to the attach point method onClick.
In summary, you can make your widget open to extension but closed to modification by adding an extension point to its event call chain.
Step 3a: connect instead of override
What if you don't want to override the extension point, but want it to execute and then have something custom execute? Just use type="dojo/connect" instead of type="dojo/method".
Step 3b: override non-extension points
In Step 3, we overrode an extension point the widget author helpfully provided for us. But if want to, we can override
any of the widget's methods. For example, to override Button.js' _onClick method, we can do:
<button dojoType="dijit.form.Button">
<script type="dojo/method" event="_onClick">
this.inherited(arguments); // call the _onClick code
</script>
</button>
Naturally, this works for dojo/connect as well.
Step 3c: a constructor
If you specify dojoType="dojo/method" without an event attribute, then the code inside that tag will be executed after the widget is created. Specifically, in the widget creation life cycle, it will run after _Widget.js::dijit._Widget->create (which calls, in that order, postMixInProperties, buildRendering, and postCreate).
Notation conventions
DOM events are all lower case, so widget events should never be. Widget methods that begin with an underscore are, by convention, private or protected. If private, only the widget they belong to should call them. If protected, only widgets in the same directory should call them. But this is only a convention, and it is not always adhered to. So while an extension point should not begin with an underscore, don't be surprised if you find some that do.
Conclusion
To sum up, this sample code illustrates how you can add overrides, connections, and a constructor to the dijit.form.Button widget.
[File: any html file using dijit.form.Button]
<div dojoType="dijit.form.Button">
<script type="dojo/method" event="onClick" args="evt">
alert("This will execute instead of the Button dijit's onClick method.");
</script>
<script type="dojo/connect" event="onClick" args="evt">
alert("This will execute after of the Button dijit's onClick method has been called.");
</script>
<script type="dojo/method">
alert("This will execute immediately after the Button dijit has been created.");
</script>
</div>
Note that despite the name of the attribute "event", as in event="onClick", its value is not an event. Remember: onClick is just a plain old Javascript method. Dojo is misleading here; perhaps one day Dojo will change the word "event" to something more appropriate like "method" of "function".
Given a widget, how can you find the plain old Javascript methods to override or "connect" to (in the dojo sense of dojo.connect)? Well, that can be very frustrating. First, you have to look inside the widget. Or inside its ancestors/superclasses. Or theirs. Or theirs. Not fun. Second, they aren't named consistenly. Sometimes an underscore in front of a method name (_) means the method is private (and therefore not an extension point), but sometimes it means protected (in which case it might be). Sometimes widget events are camelback, sometimes they aren't; sometimes they are named for the DOM events they attach to, sometimes they aren't. Not fun at all.
Finally, the widget you are using may have already attached events to its plain old methods, in which case you won't have to re-attach them with dojoAttachEvent -- in other words, you can skip Step 1. Look inside the widget's source code to see.

This work is licensed under a
Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License.