Declarative vs Programatic

The Dijit widget system expands on “Core Dojo” by providing rich, accessible and internationalized reusable components. Dojo has always had a custom declarative way of turning vanilla DOM nodes into complex widgets, but this is entirely optional, and likely faster to avoid.

There are two ways to create instances of Classes in Dojo/Dijit: Declarative and Programatic. They behave identically, though are entirely opposite approaches. For instance: to create a Dialog programatically:

   // the nodeId is not required, a node will be made for you if omitted.
   // just have to placeAt() the widget in the DOM somewhere yourself.
   new dijit.Dialog({ title:"My Dialog" }, "someNodeId");

… and the declarative equivalent:

  <div id="someNodeId" title="My Dialog" dojoType="dijit.Dialog"></div>

Both require you to setup Dojo the same way:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
 
	<title>Sample Dojo / Dijit Page</title>
 
	<!-- a Dijit theme: -->
	<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/dojo/1.3/dijit/themes/tundra/tundra.css" />
	<!-- load Dojo -->
	<script src="https://ajax.googleapis.com/ajax/libs/dojo/1.3/dojo/dojo.xd.js"></script>
 
	<script type="text/javascript">
		dojo.require("dijit.Dialog");
	</script>
</head>
<body class="tundra"></body>
</html>

The declarative way actually requires the loading of the parser module, as it is not the default behavior to allow “invalid markup”:

dojo.require("dojo.parser");
dojo.addOnLoad(function(){
      dojo.parser.parse(); // or set djConfig.parseOnLoad = true
});

The only component in Dojo/Dijit/DojoX that is “dojoType”-aware (dojoType is the custom attribute decorated on DOM nodes to identify the Class they should be turned into) is the dojo.parser … Without the dojo.parser, the dojoType is simply a useless “invalid attribute*” which will be ignored by all browsers. With the dojo.parser, these nodes will be automatically converted into the rich components expected.

Anything that can be created with a dojoType can be created with pure JavaScript using the ‘new’ function. Rather than actually carry on about how to do it, I’ve prepared two identical pages. The programatic version would likely pass W3C validation if the <script> content were extracted into an external file or wrapped in CDATA tags, but that is not the exercise here.

Dijit 1.3 Layouts:

  • Programatic Complex Layout
  • Declarative Complex Layout

The setup of either page is identical, and mirrors the sample above: provide a theme css file, link to dojo.js (dojo.xd.js in the cross-domain case), a script area for code, and a body class=’tundra’ to enable the theme.

The difference comes in the creation. The programatic example has a “buildUI” function, which is called by dojo.addOnLoad. The declarative example replaces the buildUI function with a call to dojo.parser.parse(). The buildUI function systematically builds up the layout creating nodes along the way. The declarative example uses the nodes in the DOM already and converts them. The mapping is 1:1.

By using the programatic way, we a) eliminate validation warnings b) speed things up a bit by avoiding DOM querying and c) avoid having unrendered content on the screen when the page loads. Big wins all around!

I personally prefer the programatic way, though having the optional dojoType attribute makes prototyping my code/widgets/layout much faster — and that’s what it is all about — developer ease. It is very easy to switch working code between declarative and programatic styles.

* though I still maintain the validater is “broken”. The spec states unidentified attributes are to be ignored by the browser, and — oddly — all of them do, though the W3C validater does not respect this rule.

Tags: