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

  • 5 Ways that CSS and JavaScript Interact That You May Not Know&nbsp;About

    CSS and JavaScript:  the lines seemingly get blurred by each browser release.  They have always done a very different job but in the end they are both front-end technologies so they need do need to work closely.  We have our .js files and our .css, but...

  • 5 Awesome New Mozilla Technologies You&#8217;ve Never Heard&nbsp;Of

    My trip to Mozilla Summit 2013 was incredible.  I've spent so much time focusing on my project that I had lost sight of all of the great work Mozillians were putting out.  MozSummit provided the perfect reminder of how brilliant my colleagues are and how much...

Incredible Demos

  • DWRequest: MooTools 1.2 AJAX Listener &#038; Message&nbsp;Display

    Though MooTools 1.2 is in its second beta stage, its basic syntax and theory changes have been hashed out. The JavaScript library continues to improve and become more flexible. Fellow DZone Zone Leader Boyan Kostadinov wrote a very useful article detailing how you can add a...

  • Create a Download Package Using MooTools&nbsp;Moousture

    Zohaib Sibt-e-Hassan recently released a great mouse gestures library for MooTools called Moousture. Moousture allows you to trigger functionality by moving your mouse in specified custom patterns. Too illustrate Moousture's value, I've created an image download builder using Mooustures and PHP. The XHTML <div id="messager">Waiting...

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!