Open Source Software Technical Articles

Want the Best of the Wazi Blogs Delivered Directly to your Inbox?

Subscribe to Wazi by Email

Your email:

Connect with Us!

Current Articles | RSS Feed RSS Feed

How to Create a Custom Dojo Component

  
  
  

Dojo is a powerful user interface framework used for building interactive web applications. Though it bundles a great deal of functionality, you can also extend it by creating custom components. Let's see how.



Dojo provides a collection of JavaScript utilities that solve many problems faced by the web developers. The software comprises a number of modules: Dojo base, Dojo core, Dijit, and DojoX. Dojo base is the foundation of the Dojo Toolkit, and includes mainly DOM, Ajax, and animation APIs. Dojo core provides a set of components built on top of the Dojo base that includes drag-and-drop APIs, localization and internationalization components, and data store APIs. Dijit is a comprehensive widget system that provides all core UI components and utilities. DojoX provides a set of advanced components that includes graphics libraries, mobile components, and other experimental components.



Although Dojo offers a comprehensive set of rich components for the web developers, sometimes a business needs a higher level of abstraction for more business-oriented reusable components. Such components might be a composite of two or more Dojo components, or an extension to an existing component to support a new feature that's not supported directly by the framework.



Fortunately, Dojo offers a neat mechanism for creating custom components, as you'll see here. The example code here is tested with both Dojo 1.4 and 1.7; it should work fine with all future pre-Dojo 2 releases.



In this lesson, you will create a "hello world" custom Dojo component as shown in the figure below:





Creating a custom Dojo component involves five basic steps:



Create the Component Structure



Organizing the component structure from the beginning helps a lot in updating and maintaining the Dojo component later on. One of the suggested structures uses a parent folder (I usually call mine "custom"), under which are three items:




    • The widget class or classes

    • A templates folder, which contains the component HTML templates

    • A CSS folder, which contains the component CSS files



Create Widget Template



One of the best practices for creating Dojo widgets is to separate the widget template from the widget class. The following listing shows the template of our custom component:




<div>
Hello <span dojoAttachPoint="nameNode"
class="highlightedName">
${sayHelloTo}
</span>
</div>


The component template should have one and only one parent tag. Here it is the <div> tag. The dojoAttachPoint attribute represents a reference to the DOM element for every component instance. In other words, the Dojo attach point is a clean mechanism for referring to the HTML elements of the component without needing to use the IDs of the HTML elements. The main purpose of the Dojo attach point is to avoid a collision if you have more than one instance of the Dojo component in the same page. The ${attribute} expression refers to the value of a defined component attribute. In our case, ${sayHelloTo} refers to the value of the sayHelloTo attribute of our custom Dojo component.



Create Widget Class



To create the widget class, I extend two main Dojo classes:




    • dijit._Widget is the base class for the Dijit widgets. Although dijit._Widget is deprecated in Dojo 1.7 in favor of dijit._WidgetBase, it still works fine with 1.7.

    • The dijit._Templated class is used for reading HTML templates and creating the widget's DOM tree. dijit._Templated is also deprecated in Dojo 1.7 in favor of dijit._TemplatedMixin, but it too still works fine.



Let's look at the details of the widget class code:




dojo.provide("custom.helloWorldWidget");

dojo.require("dijit._Templated");
dojo.require("dijit._Widget");
dojo.require("dijit.Tooltip");

dojo.declare("custom.helloWorldWidget", [ dijit._Widget, dijit._Templated ],
{
templatePath: dojo.moduleUrl("custom","templates/helloWorldWidget.html"),

/* Define your component custom attributes here ... */
sayHelloTo: "",

constructor: function() {
// add here anything that will be executed in the widget initialization.

},

postCreate: function() {

// add here anything that will be executed after the DOM is loaded and ready.
// For example, adding events on the dojo attach points is suitable here.
var localSayHelloTo = this.sayHelloTo;

// Show a Dojo tooltip on the user name node.
new dijit.Tooltip({
connectId: [this.nameNode],
label: "The selected name is: " + this.sayHelloTo
});

// Attach an onclick event on the user name node.
dojo.connect(this.nameNode, "onclick", function (event) {
alert("The selected name is: " + localSayHelloTo);
});
}
});


The dojo.provide is a core part of the Dojo module system. The dojo.provide("custom.helloWorldWidget") statement informs the Dojo loader that a specific module has been loaded with the name "custom.helloWorldWidget". The consumers of this component should use the dojo.require("custom.helloWorldWidget") statement to load the component.



Dojo calls the widget constructor when the widget is instantiated. You can add any initialization code for the widget in its constructor.



Dojo calls the postCreate method when the DOM elements are loaded and ready for actions. The postCreate method is a good place for attaching events to the DOM elements of the component. In our example, an onclick event is attached to the nameNode (the attach point I define in the template), and displays the sayHelloTo attribute in an alert message.



A Dojo tooltip is also attached to nameNode. It will appear when a user makes a mouseover action on the attach point.



In every widget class you have to define the component attributes. In this case, we have only one attribute defined in the widget class: the (sayHelloTo) attribute.



The templatePath property defines the path of the HTML template file of the widget class. Based on the HTML template file, the dijit._Templated class creates the widget's DOM tree.


19a98812-f823-48dc-841e-bf029c63c6d7

Style the Component



Once we have a widget template and a widget class, we can style the component. For this example I created a file called custom.css that includes the style class of the component. As you can see from the listing below, it is a very simple style.




.highlightedName {
font: italic bold 30px serif;
}


Test the Component



To test the component, you have to register the helloWorldWidget module path in an HTML page using the dojo.registerModulePath Dojo API. This API takes two arguments: the module name and the module path. You must also load the helloWorldWidget module using the dojo.require("custom.helloWorldWidget") Dojo API as shown in the listing below.




<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<script src="dojo/dojo/dojo.js" djConfig="parseOnLoad: true">
</script>

<link href="dojo/custom/css/custom.css" rel="stylesheet" type="text/css"/>

<script type="text/javascript">
dojo.registerModulePath("helloWorldWidget","custom/helloWorldWidget");

dojo.require("dojo.parser");
dojo.require("custom.helloWorldWidget");
</script>

<link rel="stylesheet" type="text/css" href="dojo/dijit/themes/tundra/tundra.css"/>
</head>

<body class="tundra">
<span dojoType="custom.helloWorldWidget" sayHelloTo="Hazem Saleh"></span>
</body>

</html>


Finally, we use the component by creating a span element whose Dojo type is custom.helloWorldWidget, with a specific value in the sayHelloTo attribute. Using the djConfig="parseOnLoad: true" statement, the Dojo parser works after the DOM elements are loaded and the custom.helloWorldWidget component is instantiated and executed.

You can download the full component code from Wazi.




This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.


This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.

Comments

Currently, there are no comments. Be the first to post one!
Post Comment
Name
 *
Email
 *
Website (optional)
Comment
 *

Allowed tags: <a> link, <b> bold, <i> italics