A common error when using Dijits is “Tried to register widget with id==XXX but that id is already registered”. That is the dijit/registry
telling us that we’ve made a mistake instantiating a widget.
When a widget is initialized, it identifies itself with registry
using its id
which registry
expects to be unique. An error will occur when you try to register that same id
again.
Below are some examples of when this error occurs.
Assigning widget ids in a template
When a widget template assigns widget ids, that template cannot be used more than once in a page.
HTML
<div id="widget1"></div>
<div id="widget2"></div>
Template
<div>
<input type="text" data-dojo-type="dijit/form/TextBox" id="name" />
</div>
JavaScript
require([
"dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_Templated",
"dijit/_WidgetsInTemplateMixin",
"dojo/text!./templates/Widget.html",
"dijit/form/TextBox"
], function (declare, _WidgetBase, _Templated, _WidgetsInTemplateMixin, template) {
var Widget = declare([_WidgetBase, _Templated, _WidgetsInTemplateMixin], {
templateString: template,
widgetsInTemplate: true
});
var widget1 = new Widget({}, "widget");
// Instantiating the widget again will fail.
var widget2 = new Widget({}, "widget");
});
Assigning widget ids in an HTML page
It is bad practice for two DOM nodes to have the same id, but two widgets with the same id will cause the Dojo parser to fail.
HTML
<div data-dojo-type="app.MyWidget" id="widget"></div>
<div data-dojo-type="app.MyWidget" id="widget"></div>
JavaScript
require([
"dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_Templated",
"dojo/parser"
], function (declare, _WidgetBase, _Templated, parser) {
declare("app.MyWidget", [_WidgetBase, _Templated], {
templateString: "<div>This is my widget!</div>"
});
parser.parse();
});
Improperly destroying a widget
The registry
needs to know when a widget is destroyed.
HTML
<div id="container">
<div id="widget"></div>
</div>
JavaScript
require([
"dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_Templated"
], function (declare, _WidgetBase, _Templated) {
var Widget = declare("app.MyWidget", [_WidgetBase, _Templated], {
templateString: "<div>This is my widget!</div>"
});
var myWidget = new Widget({}, "widget");
document.getElementById("container").innerHTML = "";
// Instantiating the widget again will fail because the
// registry still holds a reference to the first one.
myWidget = new Widget({}, "widget");
});
Do you have one of these problems? Let’s talk about solutions.
Avoid assigning ids to widgets whenever you can and if you must, make sure all of the ids in your HTML page are unique.
Never assign ids to widgets in templates. Use the data-dojo-attach-point
attribute and the Dojo parser will create a reference to the child widget in your widget. In this example, our widget will have a name
property containing a reference to the TextBox
widget.
<div>
<input type="text" data-dojo-type="dijit/form/TextBox"
data-dojo-attach-point="name"/>
</div>
Do not assign ids in templates for the purpose of styling, use CSS classes instead.
<div>
<input type="text" class="myTextBox"
data-dojo-type="dijit/form/TextBox"
data-dojo-attach-point="name"/>
</div>
Always use _WidgetBase.destroy
or _WidgetBase.destroyRecursive
to remove a widget.
myWidget.destroyRecursive();
This will not only remove your widget from the registry
but will release resources and remove the widget from the DOM. Use destroy
if your widget has no child widgets and use destroyRecursive
if it does.
The “already registered” error can be frustrating and sometimes hard to track down, but as you can see, it is pretty easy to fix.