Creating Dojo Widgets Programmatically or Declaratively

By  on  

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?

Recent Features

  • By
    CSS @supports

    Feature detection via JavaScript is a client side best practice and for all the right reasons, but unfortunately that same functionality hasn't been available within CSS.  What we end up doing is repeating the same properties multiple times with each browser prefix.  Yuck.  Another thing we...

  • By
    How I Stopped WordPress Comment Spam

    I love almost every part of being a tech blogger:  learning, preaching, bantering, researching.  The one part about blogging that I absolutely loathe:  dealing with SPAM comments.  For the past two years, my blog has registered 8,000+ SPAM comments per day.  PER DAY.  Bloating my database...

Incredible Demos

  • By
    HTML5&#8217;s placeholder Attribute

    HTML5 has introduced many features to the browser;  some HTML-based, some in the form of JavaScript APIs, but all of them useful.  One of my favorites if the introduction of the placeholder attribute to INPUT elements.  The placeholder attribute shows text in a field until the...

  • By
    Introducing MooTools HeatMap

    It's often interesting to think about where on a given element, whether it be the page, an image, or a static DIV, your users are clicking.  With that curiosity in mind, I've created HeatMap: a MooTools class that allows you to detect, load, save, and...

Discussion

  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. iDVB

    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 programmatically ALSO pass the action so that myFormWidget.action == “myForm.php”?

    • iDVB

      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.

      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 programmatically ALSO pass the action so that

      myFormWidget.action == “myForm.php”?
    • iDVB

      no idea why its still stripping….

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

  3. steve

    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. Howl

    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

    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.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!