One huge feature that sets the Dojo Toolkit apart from other JavaScript libraries is its UI component system: Dijit. A flexible, comprehensive collection of Dojo modules (complemented by corresponding resources like images, CSS files, etc.), Dijit allows you to create flexible, extensible, stylish widgets. To learn how to install, configure, and use basic Dijits within your web application, keep reading!


themes

Requiring Proper Modules and Resources

Since Dijit includes a collection of UI components, it comes bundled with four supported themes: nihilo, soria, tundra, and claro. Each theme contains images and CSS files to control the overall display of the widgets. CSS files must be explicitly included into each HTML page:


In the body tag of your page, or in a parent node of your widgets, you need to define the class name based upon the theme you would like to use.

<body class="claro">

You can view each theme set using the Dijit Theme Tester. You may also define your own theme.

dojoConfig

There are many options for dojoConfig but the two most important are async and isDebug. You’ll want isDebug set to true during development so you get proper warning messages. async is the setting to tell the AMD loader to use the new, faster way to load JavaScript modules.

	dojoConfig = {
		isDebug:true,
		async:true
	};

Note: parseOnLoad was a common property in djConfig, but this is no longer recommended. See information about the parser below.

dojoConfig is a global and must be set before you load Dojo, or else it will be ignored. You can also set the configuration as an attribute on the script file, in which case you would use data-dojo-config:

<script src="//ajax.googleapis.com/ajax/libs/dojo/1.8/dojo/dojo.js"
	data-dojo-config="isDebug:true, async:true" type="text/javascript"></script>

It’s time to add a widget. A quick test is to drop a button into the page first thing, to check that everything is set up and parsing correctly.

<body class="claro">
	<button data-dojo-type='dijit/form/Button'>Clicky</button>
</body>

parse1

dojo/parser

As you can see, the widget didn’t parse correctly. We need to load dojo/parser and explicitly tell it to parse. When do we do this? After the DOM is ready of course. The AMD way to determine this is with the dojo/domReady plugin. AMD is instructed that the loaded dependency is a plugin with an exclamation point, such as: dojo/domReady!. Because we won’t need Dojo to do any work before any parsing, we can safely put this code at the bottom of the body:

<body class="claro">
	<button data-dojo-type='dijit/form/Button'>Clicky</button>
	<script>
		require([
			'dojo/parser',
			'dojo/domReady!'
		], function(parser){
			parser.parse(); // tell dojo to check the DOM for widgets
		});
	</script>
</body>

parser2

The widget parsed with the claro theme, but there is a warning in the console: WARNING: Modules being Auto-Required: dijit/form/Button. This message is shown because the widget was never specifically required anywhere, and to get maximum performance from your application, AMD and Dojo require that you explicitly define the modules and dependencies you want to use in your application. The Dojo 1.8 parser is a bit more forgiving. It is asynchronous and smart enough to find and load un-required modules. It’s not recommended to develop this way, as it’s slower than having the module already loaded before you’re trying to parse and render, but it’s helpful that it catches the mistake and then lets us know without breaking the application. Dojo 1.7 would simply fail with an error warning. Adding dijit/form/Button to the require dependencies fixes this issue and improves our performance.

One of the most notable features of the Dijit system is that you may create a Dijit widget in one of two ways: declaratively, using HTML markup and custom attributes; or programmatically, using raw JavaScript. Let’s take a look at how we can make a basic select element a Dojo-enhanced widget.

Creating Widgets

The Basic select Element

<select name="character" id="character">
	<option value="">Select a character</option>
	<option value="Leonard">Dr. Leonard Leakey Hofstadter</option>
	<option value="Sheldon" selected="selected">Dr. Sheldon Lee Cooper</option>
	<option value="Rajesh">Dr. Rajesh Ramayan Koothrappali</option>
	<option value="Howard">Howard Joel Wolowitz</option>
</select>

This is a static select element containing a series of option elements. We know we’d like for this select element to become a dijit/form/FilteringSelect widget so we must require this module.

require([
	'dojo/parser',
	'dijit/form/FilteringSelect',
	'dojo/domReady!'
], function(parser, FilteringSelect){
	parser.parse();
});

Now that the dijit/form/FilteringSelect module is available, and the parser is looking for widgets in the DOM, we can use the declarative or programmatic method of enhancing our select element.

Declarative Method

The declarative method of enhancing the select element is done within the HTML element itself:

<select name="character" id="characterNode"
	data-dojo-type="dijit/form/FilteringSelect"
	data-dojo-props='autoComplete:true, pageSize:10' >
	<option value="">Select a character</option>
	<option value="Leonard">Dr. Leonard Leakey Hofstadter</option>
	<option value="Sheldon" selected="selected">Dr. Sheldon Lee Cooper</option>
	<option value="Rajesh">Dr. Rajesh Ramayan Koothrappali</option>
	<option value="Howard">Howard Joel Wolowitz</option>
</select>

This declarative example illustrates the use of the data-dojo-type attribute that identifies which Dijit the given element should become. When we call parser.parse(), Dojo will find this element and instantiate and initialize the widget.

Options of the dijit/form/FilteringSelect module are also custom attributes. This widget will autocomplete when the user types a value and page every 10 items. Just as with a normal select element, “Sheldon” will be selected initially.

Programmatic Method

The programmatic method of enhancing the select element is done completely with JavaScript:

	require([
	'dijit/form/FilteringSelect',
	'dojo/domReady!'
], function(FilteringSelect){

	var filteringSelect = new FilteringSelect({
		autoComplete: true,
		pageSize: 10
	},'characterNode');

});

Note that dojo/parser was removed from the list of dependencies, as it’s not needed for programmatic instantiation of widgets.

We can create other widgets the same way:

require([
	'dijit/form/FilteringSelect',
	'dijit/form/DateTextBox',
	'dijit/form/TimeTextBox',
	'dijit/form/Textbox',
	'dijit/form/Textarea',
	'dijit/form/Checkbox',
	'dijit/form/RadioButton',
	'dojo/domReady!'
], function(FilteringSelect, DateTextBox, TimeTextBox, Textbox, Textarea, Checkbox, RadioButton){

	var filteringSelect = new FilteringSelect({
		autoComplete: true,
		pageSize: 10
	},'characterNode');

	var input = new Textbox({/*options*/},'myInputNode');
	var textarea = new Textarea({/*options*/},'myTextareaNode');
	var mySelect = new FilteringSelect({/*options*/},'mySelectNode');
	var date = new DateTextBox({/*options*/},'myDateNode');
	var time = new TimeTextBox({/*options*/},'myTimeNode');
	var checkbox = new CheckBox({/*options*/},'myCheckboxNode');
	var radio1 = new RadioButton({/*options*/},'myRadio1Node');
	var radio2 = new RadioButton({/*options*/},'myRadio2Node');
});

If you have a large form and don’t have the desire to add all the markup to individual elements for Dijitization, you could build your own mini-parser to create Dijits by selector:

require([
	'dojo/query',
	'dijit/form/FilteringSelect',
	'dijit/form/Button',
	'dijit/form/CheckBox',
	'dijit/form/RadioButton',
	'dojo/domReady!'
], function(query, FilteringSelect, Button, CheckBox, RadioButton){

	query('button,select,input').forEach(function(node){
		var type = node.nodeName;
		if(type === 'INPUT'){
			type = node.type.toUpperCase();
		}
		switch(type){
			case 'BUTTON':
				new Button({},node); break;
			case 'SELECT':
				new FilteringSelect({},node); break;
			case 'RADIO':
				new RadioButton({},node); break;
			case 'CHECKBOX':
				new CheckBox({},node); break;
		}
	});
});

Of course, this simple example isn’t converting the node attributes into properties and providing them to the widget, nor are any of the other special features of dojo/parser being done.

Accessing Dijit Widgets and their Properties

Accessing a specific DOM element can be easily accomplished by using the dojo/dom.byId method. Dijit has its own dijit/registry.byId method which retrieves the Dijit widget registered with the ID specified. If the element to be made a Dijit has an ID, the widget ID will be that same value. If the source element doesn’t have an ID attribute, a widget ID will be generated. If we wanted to retrieve the widget object for the declaratively created “characterNode” Dijit above, we would code:

require([
	'dojo/parser',
	'dijit/registry',
	'dijit/form/FilteringSelect',
	'dojo/domReady!'
], function(parser, registry, FilteringSelect){
	parser.parse();
	var filteringSelect = registry.byId('characterNode');
	console.log('filteringSelect', filteringSelect);
});

Dijit Form
View a listing of all properties and methods of a Dijit using registry.byId within Firebug.

If we wanted to access the pageSize property for which the Dijit widget was created from, we would access it with a Dijit getter:

	var pageSize = registry.byId('characterNode').get('pageSize'); // returns 10

If we wanted to change the pageSize for the widget, we would code:

	registry.byId('characterNode').set('pageSize',20); //now pageSize is 20

Note: Dojo 1.5 introduced “get” and “set” methods to handle property values. In Dojo 1.4 and earlier, you would use “attr” in place of both get and set in the previous example.

Listening to Widget Events

Dijit widgets use dojo/on method to listen to DOM events on the given widget:

filteringSelect.on('change', function(value){
	console.log('value', value);
});

Each widget supports a select number of events so be sure to view the documentation for the widget to ensure the event you’d like to listen to is supported.

It’s important to note that those are DOM events. If you wish to listen to a widget method, you should use dojo/aspect:

require([
	'dojo/aspect'
	// other deps...
], function(aspect){
	aspect.after(filteringSelect, 'validate', function(value){
		console.log('validate', value);
	});
});

The Dijit Collection

Dijit is also an incredible UI library that has the potential to enhance your website and save you an immense amount of time in doing so. Dijit includes a large number of solid widgets including:

  • Context, popup, and dropdown menus
  • Form element replacements like buttons, combo boxes, checkboxes, radio buttons, and text boxes
  • Date and time selection widgets
  • WYSIWYG Editor
  • Horizontal and Vertical Sliders
  • Progress Bars
  • Tabs and Accordions
  • Tree Structures (including Drag and Drop)
  • Dialogs and Tooltips
  • Layout widgets with slide controls and splitters

And if Dijit doesn’t have a widget you want, there’s a good chance it’s available in DojoX (Dojo Extensions)! To see many of these widgets in action, visit the Dojo Theme Tester. Or, if you’re looking for an amazing grid component, you should check out dgrid.

Dijit Resources

The following resources will help to aid your Dijit education:

Dijit contains a vast array of useful widgets to enhance your website!