Ashley Ashley - 10 days ago 5
Javascript Question

dojo: destroy all widgets by dom node

My content is replaced with ajax but sometimes an element will have the same id on two pages (ie, a photo on the home page has the same id on the gallery page). This means that when dojo.parser.parse is called, the widgets are trying to be re-added, and the below error is thrown:

Error: Tried to register widget with id==____ but that id is already registered


Ideally, what I'd like to do is run destroyRecursive on the DOM node that the AJAX replaces. I've tried both of the below but neither work (I believe destroyRecursive is for widgets not DOM?):

dojo.byId('main').destroyRecursive();
dijit.byId('main').destroyRecursive();


Is there a good way of doing this, or do I need to try and ensure that all my id's are different?

Answer

You are on the right track, and you are correct that destroyRecursive only exists on widgets. However, there are a couple of choices to accomplish what you want to do.

If you're using widgets to a significant extent, and the div in question is regularly being used as a bucket to hold content including widgets, then I would highly recommend you have a look at dijit.layout.ContentPane. ContentPane is a widget primarily focused around the idea of a container that receives content, either directly or from a URL, which may or may not include widgets.

Right now you're probably doing something like this on each page change:

dojo.xhrGet({
    url: 'something.html',
    load: function(html) {
        dojo.byId('main').innerHTML = html;
        dojo.parser.parse(dojo.byId('main'));
    }
    error: function(error) { ... }
});

With a ContentPane, you could do the same thing like this:

cp.set('href', 'something.html'); //use attr instead of set if < dojo 1.5

With this, ContentPane will not only fetch that URL and hold its contents - it will also parse any widgets within it - and equally importantly, it will automatically destroy any existing widgets within itself before it replaces its content.

You can read more about it in the Dojo documentation:

Alternatively, if you don't feel like using a widget to hold your content, you can look for widgets in your div and destroy them yourself. Here's the easiest way to do it:

dojo.forEach(dijit.findWidgets(dojo.byId('main')), function(w) {
    w.destroyRecursive();
});