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
    Animated 3D Flipping Menu with CSS

    CSS animations aren't just for basic fades or sliding elements anymore -- CSS animations are capable of much more.  I've showed you how you can create an exploding logo (applied with JavaScript, but all animation is CSS), an animated Photo Stack, a sweet...

  • By
    Create a CSS Flipping Animation

    CSS animations are a lot of fun; the beauty of them is that through many simple properties, you can create anything from an elegant fade in to a WTF-Pixar-would-be-proud effect. One CSS effect somewhere in between is the CSS flip effect, whereby there's...

Incredible Demos

  • By
    9 Incredible CodePen Demos

    CodePen is a treasure trove of incredible demos harnessing the power of client side languages.   The client side is always limited by what browsers provide us but the creativity and cleverness of developers always pushes the boundaries of what we think the front end can do.  Thanks to CSS...

  • By
    Create a 3D Panorama Image with A-Frame

    In the five years I've been at Mozilla I've seen some awesome projects.  Some of them very popular, some of them very niche, but none of them has inspired me the way the MozVR team's work with WebVR and A-Frame project have. A-Frame is a community project...

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!