DOM nodes vs. Dojo widgets (dojo.byId vs. dijit.byId)

The headline pretty much reveals the secret. But let’s dive into the details anyway.
This cookie will try to explain the differences between dojo.byId(), dijit.byId(), dijit.byNode() and dijit.getEnclosingWidget(). And when you should use what and what you should expect them to return and where you can use them.

Going forward and back between the actual DOM node and a dojo widget (dijit) is one of the basic tasks one is doing when working with a UI oriented, dijit based application. And therefore the way the interaction of the DOM tree and the actual dijit you finally are working with are very important and also allow you to customize stuff easier. Especially when you want to customize the appearance (CSS), behaviour (connect on events) or the functionality itself (extending or overriding).

Use a dijit
Let’s create a beautiful button using a dijit, as easy as that:

<button id="btn" dojoType="dijit.form.Button">Click me</button>

dijitButtonAfter your page was rendered you can see a much nicer button, styled and licked.
Until before dojo we all used to do

var node = document.getElementById("btn")

forget about it and do this

var node = dojo.byId("btn")

Remember you took the red pill! Now node contains a reference to the DOM node. You can try playing around with that but you will give up frustrated since this is not the way it’s meant to work and dojo offers you a much nicer way to do much more with this button than DOM can offer.

To get a reference to the actual dijit (the JavaScript object) you can call

var widget = dijit.byId("btn")

If you are lazy (like me) you can explore widget simply by using FireBug and the TAB key. FireBug says something like this about widget

[Widget dijit.form.Button, btn] _connects=[4] _attaches=[0] id=btn params=Object

You will also see that the object has a lot of interesting properties and even more interesting methods. For example something like

widget.setLabel("Know me");
widget.setAttribute("disabled", true)

Now the button text has changed and it is disabled. Wow, pretty easy I think.

dojo.byId() vs. dijit.byId()
As you saw, dojo.byId() returns the reference to a DOM node, so the real basic node that is rendered by the browser. But dijit.byId() returns the dijit reference for the widget dojo has built for you while parsing your HTML file and rendering it to what you finally see. But why are they different? Because what the dijit generated is made up out of more than the actual one tag you have written in you original HTML file. Your tag is being replaced by something like the following

<div class="dijit dijitReset dijitLeft dijitInline dijitButton" wairole="presentation" dojoattachevent="onclick:_onButtonClick,onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse" role="wairole:presentation" widgetid="btn">
	<button id="btn" class="dijitReset dijitStretch dijitButtonNode dijitButtonContents" waistate="labelledby-btn_label" wairole="button" type="button" dojoattachpoint="focusNode,titleNode" role="wairole:button" aaa:labelledby="btn_label" tabindex="0" style="-moz-user-select: none;">
		<span class="dijitReset dijitInline" dojoattachpoint="iconNode">
			<span class="dijitReset dijitToggleButtonIconChar"></span>
		</span>
		<div class="dijitReset dijitInline">
			<center id="btn_label" class="dijitReset dijitButtonText" dojoattachpoint="containerNode">
				Click me
			</center>
		</div>
	</button>
</div>

Wow, that looks like a lot of stuff. But remember that a dijit is way more powerful than the normal HTML elements currently are. Note the attributes “dojoattachpoint”, those are the points that a dijit provides you to directly access the DOM nodes, if you really want to (and know what you are doing). So to directly access the inner node that contains the actual button text that we are seeing and modifying it the hard core way you could do

widget.containerNode.innerHTML = "Hard-core button"; // Hack!

But that is not the suggested way! You might already see that the button is not properly resized to make the text fit in there, so there is already a simple reason why to rather use widget.setLabel().

widget.setLabel("Hard-core button"); // Nice!

The way back
Sometimes you might want to know the way back, that is from you DOM node to the widget. Simply use dojo.getEnclosingWidget() like so

dijit.getEnclosingWidget(dojo.byId("btn"))

This shows how to get the dijit reference also when you just know one of the nodes inside of it. (Of course the same can be done with the much shorter dijit.byId(”btn”)).

Have fun diving into the dijits!

Tags: ,