Dojo FAQ: Why am I getting “Error: Tried to register widget with id==xxx but that id is already registered”?

By on October 23, 2013 10:05 am

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: "
This is my widget!
" }); 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: "
This is my widget!
" }); 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.

Comments

  • Ken Franqueiro

    It is worth noting that if for some reason you really cannot avoid assigning IDs in a widget template (e.g. for form fields which will have labels associated), you can do it *but* you should ensure its uniqueness, usually by prepending the id of the parent widget. e.g. id=”${id}_someId”

  • mchyzer .

    I think this is a bug. If dojo has declarative markup, then it is saying you can do things like you would HTML. So if I am replacing div’s with ajax, I dont think twice if an HTML id is the same as one in a div it replaced (or replaced before that). I shouldnt have to unregister dojo widgets, it should just replace whatever was replaced there beforehand and not throw an error. I know you might think you are helping people who accidentally have two on a page, maybe there could be a switch to enable an error being thrown, or it could just write to the console without an error. They will just have to do the same troubleshooting they do with HTML.

    Thanks,
    Chris

  • If you have parseOnLoad: true in dojoConfig then make it false and include

    require([

    “dojo/parser”,
    “dojo/domReady!”

    ], function(parser){
    parser.parse();
    });

    after the dojo.js path file declaration.

  • Hi there, is this a question or just a general comment? If the latter, then yes, agreed, if a question, then please let us know what you’re trying to determine.

  • Hey Dylan,

    That was a comment/solution my friend.. :)

  • anchorite

    Thank you for this, the .destroyRecursive() function fixed my problem. The regular .destroy() whose help page claims “dojo.destroy deletes all children and the node itself” doesn’t seem to remove the ID from the registry, which IMO it would given that language, but at least I have this workaround.