xstyle_transparentA 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.