Dojo: Asynchronous Module Definition (AMD)
January 23, 2012Tested with: Dojo Toolkit 1.7.1
From version 1.6, the Dojo team started the refactoring of Dojo toolkit in order to make it compliant with the CommonJS AMD API. AMD allows to create more efficient scripts, to use different toolkits in the same web application avoiding conflicts and much more. In version 1.7, the refactoring has been completed and this release is also the base to start the migration to Dojo 2.0.
In this post, I explain how to migrate old code to the new style exploiting AMD module format.
Configuration
First of all we have to configure Dojo in order to use asynchronous features.
<script type="text/javascript">
var dojoConfig = {
baseUrl: "js",
isDebug: true,
parseOnLoad: false,
// enables AMD loader
async: true,
// modulePaths parameter is deprecated
packages: [
{
name: "dojo",
location: "dojo"
},
{
name: "dijit",
location: "dijit"
},
{
name: "foo",
location: "info/eliacontini"
}
]
};
</script>
<script type="text/javascript" src="js/dojo/dojo.js"></script>
The above configuration works with the following directories layout.
project/
css/
img/
js/
dijit/
dojo/
dojox/
info/
eliacontini/
FooWidget/
nls/
en/
lang.js
lang.js
template/
FooWidget.html
FooWidget.js
index.html
After we configured Dojo, we are able to call our FooWidget and to use it in our web application.
<script type="text/javascript">
require(["foo/FooWidget"], function(Foo) {
var someVar = new Foo();
/* ... do something with someVar ... */
});
</script>
Writing custom widgets
Now we have to adapt our FooWidget to the AMD module format.
define([
/* dijit/_Widget is deprecated */
"dijit/_WidgetBase",
/* dijit._Templated is deprecated and
will be removed in Dojo 2.0 */
"dijit/_TemplatedMixin",
// declare function
"dojo/_base/declare",
// load template
"dojo/text!./FooWidget/template/FooWidget.html",
// load i18n strings
"dojo/i18n!./FooWidget/nls/lang"
], function(_Widget, _Templated, declare, template, i18n) {
return declare("info/eliacontini/FooWidget", [_Widget, _Templated], {
templateString: template,
_i18n: i18n,
constructor: function() {
console.log(this.templateString);
console.log(this._i18n.test);
}
});
});
In the template file remember to use HTML5 Data Attributes!
Widgets in Template
If in our template we plan to use other widgets in the declarative way, we have to extend also the dijit/_WidgetsInTemplateMixin
class.
define([
// ...
"dijit/_WidgetsInTemplateMixin"
// ...
], function(/*...,*/ _WidgetsInTemplate /*, ...*/) {
return declare(
"info/eliacontini/FooWidget",
[_Widget, _Templated, _WidgetsInTemplate],
{
// ...
widgetsInTemplate: true
// ...
}
);
});
Internationalization (I18N)
In the default language file, we have to specify the default translation and which are the available translations.
This is the default language file.
define({
root: {
test: "test root"
},
en: true // English translation available
});
In the en directory the file contains:
define({
test: "test en"
});
That's all!