Creating Dojo Widgets Programmatically or Declaratively

Written by David Walsh on September 9, 2010 · 9 Comments

The Dojo Toolkit has an awesome UI framework called Dijit.  Dijit is an expansive set of Dojo widget that allow you to create highly themeable, functional forms, layouts, and much more.  One of the highlights of Dijit, from a developer's perspective, is that you may create widgets in two ways:  declaratively and programmatically.  This blog posts aims to show you an example of each widget creation method and discuss the advantages of each.

Dojo Dijit Tabs

Required: Requiring Classes

Whether you prefer declarative or programmatic widget creation, you always need to require desired widget classes:

dojo.require('dijit.form.FilteringSelect');
dojo.require('dijit.layout.TabContainer');
dojo.require('dijit.layout.ContentPane');

With required class declarations in place, it's showtime!

Option 1: Creating Widgets Declaratively

Creating widgets "declaratively" means to create widgets using HTML markup with attributes to denote that an element should become a widget.  The first part of creating a widget declaratively is to direct dojo to parse the page, looking for Dojo widgets  There are two ways to do this.  The first way is to configure the djConfig variable's parseOnLoad property:

<script src="/js/dojo.js" djConfig="parseOnLoad:true;"></script>

parseOnLoad does exactly what it sounds like: parses the page as soon as all resources and DOM elements are loaded.  The other way is to explicitly tell dojo to parse the page:

//load the parser
dojo.require('dojo.parser');

//parse the page
dojo.ready(function() {
	dojo.parser.parse()
});

Now that Dojo has been told to parse the page once the DOM is ready and Dojo Toolkit assets are loaded, you can create your Dijit widgets using markup.  The dojoType attribute provides a place to declare what type of Dijit widget the element should  become:

<!-- turn a select into a "FilteringSelect" -->
<select dojoType="dijit.form.FilteringSelect">
	<option value="value1">Key 1</option>
	<!-- more options here -->
</select>

<!-- create a layout widget -->
<div dojoType="dijit.layout.TabContainer">
	<div dojoType="dijit.layout.ContentPane"><!-- content 1 here --></div>
	<div dojoType="dijit.layout.ContentPane"><!-- content 2 here --></div>
	<div dojoType="dijit.layout.ContentPane"><!-- content 3 here --></div>
</div>

Boom!  Once the DOM is ready and resources have loaded, the elements with dojoType attributes will be turned into widgets.   Widget options may be added as custom attributes keys and values:

<!-- turn a DIV into a "FilteringSelect"; options will come from data store -->
<div dojoType="dijit.form.FilteringSelect" store="optionsStore" searchAttr="val">
	<!-- options come from a data store -->
</div>

<!-- create a layout widget; contentpane has custom attributes for JS -->
<div dojoType="dijit.layout.TabContainer">
	<div dojoType="dijit.layout.ContentPane" closable="true" href="somepage.php" preload="true">
	<!-- content 1 here -->
	</div>
</div>

Sweet, no?  Think of how much time you can save by embedding widget types and options within the elements themselves.

Option 2: Creating Widgets Programmatically

To create a widget programmatically, you create DOM nodes which act as placeholders for the future widget:

<button id="makeMeAWidget">Click Me</button>

Once the DOM and all dependencies have loaded, you must explicitly add JavaScript to turn the HTML element into a widget.

//when dependencies are loaded...
dojo.ready(function() {
	//...make elements into widgets
	var widget = new dijit.form.Button({},'makeMeAWidget'); //options,elementID
});

Instead of individually assigning widgets to elements, you may also use dojo.behavior to find elements by selector and widgetize them:

dojo.behavior.add({
	'button': {
		found: function(button) {
			new dijit.form.Button({},button); //options,elementID
		}
	}
})

Dojo finds all elements that match the  given selector and widget-izes them.

What's Best?

There are a few things you to keep in mind when deciding which is best for your project

  • Programmatic widget creation is faster because the DOM doesn't need to be scoured to find elements that should become widgets.
  • Declarative widget creation allows you to code (and thus create widgets) faster.  If your page isn't too big, the speed difference between declarative and programmatic widget creation is very small.

So What's Your Excuse?

You've seen what Dijit can do but you haven't tried it yet.  What's your excuse?

Comments

  1. Nice :) seems Dojo Dijit is really a good choice for web apps.
    I still have to try out Google Closure. Can you try it out if possible and post please?

  2. We’re currently using Dojo and are trying to do everything programmatically so as not to sully the HTML with dojo related attr etc.

    One issue we’re running into is default html node attr not seeming to get passed when programmatically instantiating a dijit.

    Eg. I have
    I then set it up as a dijit.form.Form which works…
    …the html form node ID is still “myForm”

    var myFormWidget = dijit.byNode(dojo.byId(“myForm”));

    ..but when I test that myFormWidget.action it equals nothing.

    Shouldn’t setting a form up programatically ALSO pass the action so that myFormWidget.action == “myForm.php”?

    • Sorry
      html got stripped let me try again….

      We’re currently using Dojo and are trying to do everything programmatically so as not to sully the HTML with dojo related attr etc.

      One issue we’re running into is default html node attr not seeming to get passed when programmatically instantiating a dijit.

      Eg. I have

      I then set it up as a dijit.form.Form which works…
      …the html form node ID is still “myForm”

      I then…

      var myFormWidget = dijit.byNode(dojo.byId(“myForm”));

      ..but when I test that myFormWidget.action it equals nothing.

      Shouldn’t setting a form up programatically ALSO pass the action so that myFormWidget.action == “myForm.php”?

    • no idea why its still stripping….

      anyway… I have a form with ID=”myform” and ACTION=”myForm.php”

  3. is there a way of converting Declarative dojo to Programmatical dojo, without re-writing? thanks!!

  4. How to create a form and controls in it only programmatically?

  5. Uhh.. what is the Author’s excuse for not providing a Dojo version number to which this tutorial is supposed apply?

    1.6 merrily gives me “Uncaught SyntaxError: Unexpected token ;” for using djConfig=”parseOnLoad:true;”. It took a while before arriving to that conclusion.

    Also, there is no component called “dijit.form.TextArea”, it is supposed to be “dijit.form.Textarea”.

    Sigh… and the default components look plain terrible. Not a very good first impression about Dojo.

    • The Dojo 1.x line should support everything, so with Dojo and a basic tutorial like this, version number isn’t so much important. That said, you could view the demo and find out.

  6. Teaman June 27, 2012

    I agree, knowing what version of Dojo would be very useful here. Even a posted date would be helpful in determining what version was used. Otherwise it was a helpful post for me, helping me learn the distinction between the two ways of creating Dojo.

Be Heard

Tip: Wrap your code in <pre> tags or link to a GitHub Gist!

Use Code Editor
Older
Organized Selector Chaos with dojo.behavior
Newer
An Interview with jsFiddle Creator Piotr Zalewa