Dojo 1.6 Parser Confusion: What’s in a Widget, Anyway?

May 20, 2011 by Ken · 2 Comments 

Dojo 1.6 introduces a new alternative declarative markup syntax using HTML5 data attributes, with the aim of allowing definition of object instances via HTML without forcing users to write invalid markup. The new syntax primarily revolves around the use of data-dojo-type in lieu of dojoType, and a data-dojo-props attribute to hold any properties to be passed to the constructor’s first argument.

However, this new syntax brings with it some significant differences in behavior, which has caught many users off-guard. For instance, you might try something like this:

<input data-dojo-type="dijit.form.ValidationTextBox"
    id="tb_username" data-dojo-props="required: true"
    style="width: 300px;" name="username" value="bob">

You would be surprised, then, to observe that the widget appears to ignore your style, name, and value settings altogether. What gives? Let’s find out.

First and most importantly, the Dojo 1.6 release notes section on the parser actually does warn about this behavior:

when using data-dojo-type, all widget properties must be stashed on a single attribute: data-dojo-props

and further:

If degradation is a concern, duplicate native attributes in data-dojo-props and on the node reference, as widget parameters are no longer read from the node attributes individually.

But perhaps the true weight of this still isn’t clear. It is important to realize that widgets often define properties designed to mirror/shadow standard HTML attributes. For example, style and class are properties on all widgets; in addition, name, value, type, checked, and others exist on various form widgets.

With the legacy parser behavior, these attributes would automagically “just work”, mapping from the respective HTML attributes to widget properties (as would be done for all properties found on the widget’s prototype, regardless of HTML-standardness). Unfortunately, sometimes magic can be a double-edged sword, and this is one of those instances where it can bite those who are unaware of what actually goes on under the surface.

For example, under the legacy parser behavior, this HTML:

<input dojoType="dijit.form.ValidationTextBox" required="true" id="tb_username"
    style="width: 300px;" name="username" value="bob">

would be essentially equivalent to the following JS (leaving aside matters of placement and startup):

new dijit.form.ValidationTextBox({
    required: true,
    id: "tb_username",
    style: "width: 300px;",
    name: "username",
    value: "bob"
});

Notice how all of those attributes – even those that would be considered valid HTML – get sent to the widget constructor to be mixed in as properties. Now, think back to the release note: “all widget properties must be stashed on a single attribute: data-dojo-props.” Can you guess what’s wrong with our original markup now? Let’s fix it:

<input data-dojo-type="dijit.form.ValidationTextBox"
    data-dojo-props="id: 'tb', required: true, name: 'username', value: 'bob',
        style: 'width: 300px;'">

Note the additional single-quotes around string values within data-dojo-props – this is because data-dojo-props is essentially treated as a JS object, but with the curly braces implied (do not include outer curly braces) – essentially, the same way data-dojo-config is treated.

This markup will make the widget behave as expected, but this will render the input field useless on clients that don’t support JavaScript. Here’s where that second point from the release notes comes in: if we’re interested in graceful degradation, we’ll need to duplicate the applicable attributes both inside data-dojo-props and as standard HTML attributes. This yields the following:

<input data-dojo-type="dijit.form.ValidationTextBox"
    id="tb" name="username" value="bob" style="width: 300px;"
    data-dojo-props="required: true, name: 'username', value: 'bob',
        style: 'width: 300px;'">

Note that I made an exception in the duplication above – id can actually still be specified as a plain HTML attribute, since dijit._WidgetBase specifically checks the id attribute of the srcNodeRef if one is passed – and in the case of parsed widgets, the node being parsed is passed as the srcNodeRef.

This admittedly looks terribly redundant, and indeed a handful of contributors even took issue with this, and some users opted to continue using dojoType for the time being, as this behavior was potentially not yet finalized. From what I understand, the main factor towards the 1.6 behavior was performance. Being able to “fast-track” the parser to look squarely at a single attribute, rather than checking several individual node attributes, was a win from a performance perspective; moreover, some browsers impose funny defaults even in the absence of a specified value for some standard attributes, making the “real” value harder to discern.

However, the good news is that this behavior was indeed revised post-1.6, so that this duplicity should no longer be necessary in Dojo 1.7. In other words, when 1.7 comes around, you should be able to write the code from the top of this post, and it will in fact “just work”.

…Hopefully you’re not looking for a shoe to throw in my general direction upon reading that last paragraph, after I spent the entirety of this post explaining the behavior in 1.6. Knowledge is power, right? :)

Further Reading

Comments

2 Responses to “Dojo 1.6 Parser Confusion: What’s in a Widget, Anyway?”
  1. Val says:

    So, from what I understand, two changes happened:
    1. renaming to data-dojo-* for HTML5 compliance
    2. behavior change from dojoType to data-dojo-type to no longer parse additional attributes in order to optimize parsing and avoid some browser quirks with hidden default values

    Is that right? (I’m like two years behind but trying to catch up).

    V

    • Ken says:

      Yes, that’s right, but point 2 applies to 1.6 only. 1.7 resolved this because of the amount of confusion and backlash it got after 1.6 was released.

Speak Up