Why doesn’t myTitlePane.title = “work” ?

Newcomers to dijit often instantiate a widget and wonder why “normal” dom getter/setters don’t work to adjust the properties. There is a perfectly valid reason for this, so lets inspect.

For example, a Markup declaration of a dijit.TitlePane:

<div dojoType="dijit.TitlePane" title="Title Pane #2" id="myTitlePane" style="width: 300px;">
	<form>
		Age: <input><br>
		Discount card <input type=checkbox><br>
		<button>Submit</button><br>
	</form>
</div>

And then trying to modify the title programatically by doing:

dijit.byId("myTitlePane").title = "Hello world";

Or maybe even:

dojo.byId("myTitlePane").title = "Hello world";

Neither of these techniques work, although it might seem like they should since you can modify DOM nodes that way:

<input id="myInput">
<script>
   dojo.byId("myInput").value = "Hello world";
</script>

The reason is that there are two separate things, the DOM nodes for the widget and then a stand-alone javascript object representing the widget:

So, the title of the TitlePane is stored in two separate places.

Calling:

dijit.byId("myTitlePane").title = "Hello world";

will just modify the attribute in the JS Object, without affecting what appears in the browser:

Conversely, calling:

dojo.byId("myTitlePane").title = "Hello world";

…won’t work either, but we need to look more closely at the DOM to see why. If we use firebug we can see the DOM nodes for TitlePane. Note that there’s more than just one node:

As you can see, to modify the title you need to change what’s in that dijitTitlePaneTextNode <span>. The only effect of setting the title attribute on the outer <div> would be create a tooltip-type popup that appears when you hover the mouse anywhere over the TitlePane. Clearly not what you want…

So, this is why we use setters to control “attributes” of widgets. TitlePane has a setTitle() method that will modify both the JS Object and the corresponding DOM tree.

Note that since widgets have a lot of attributes that can be modified, and since (as anyone that programs in java knows) getters and setters can take a lot of lines of code even when they don’t do anything (other than setting/returning a variable), and since (as anyone that programs in javascript knows) code compactness is important, the form widgets use a single setter called setAttribute() that takes the attribute name and a value. (Except for value, which is controlled by setValue()/getValue().)

By the way, you might be wondering, why is “title” stored in the JS object at all? Isn’t it redundant to have it in two places? Yes, it is, and it’s in the JS object mainly due to how the parser is implemented; the parser requires that every attribute be declared in the JS object. Although I guess the good thing is consistency: some attributes (like “duration”) aren’t stored in the DOM at all. Also, having the attribute in the JS object means that we don’t need a getter, just a setter.

Tags: