Treehouse

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?

ydkjs-4.png

Recent Features

Incredible Demos

  • MooTools ContextMenu&nbsp;Plugin

    ContextMenu is a highly customizable, compact context menu script written with CSS, XHTML, and the MooTools JavaScript framework. ContextMenu allows you to offer stylish, functional context menus on your website. View Demo Download The XHTML Menu <ul id="contextmenu"> <li><a...

  • CSS&nbsp;Sprites

    The idea of CSS sprites is pretty genius. For those of you who don't know the idea of a sprite, a sprite is basically multiple graphics compiled into one image. The advantages of using sprites are: Fewer images for...

  • PHP / MooTools 1.2 Accordion&nbsp;Helper

    The MooTools Accordion plugin seems to be the plugin that people seem to have the most problems with. It's an awesome plugin, so I can see why so many people want to use it, but I think that may...

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

      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”?

    • 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!

Use Code Editor