DCTemplate User Guide

What is DCTemplate?

DCTemplate ("DOM Compiled Template") is a templating system for (X)HTML and JavaScript - it allows web developers to maintain dynamic chunks of XHTML as well-formed XML templates. The templates are "compiled" at build time to high-performance JavaScript methods.

The Problem

There are numerous options when coding JavaScript to dynamically update parts of a web page, for instance with new data coming from an Ajax (XHR) call.

innerHTML

One straightforward approach is to use the innerHTML property on the html tag you are trying to update. For example:

	document.getElementById('mydiv').innerHTML = "This is the <b>new</b> content of the div";

This code will replace the entire content of the tag with id 'mydiv' with the given string. While this is straightforward, there are a couple of disadvantages to this approach. For one, since innerHTML accepts arbitrary markup as a string there is no way to check that this markup is indeed valid HTML. This markup string can also become very difficult to read and cannot be formatted as proper (X)HTML.

Also, although supported in the major browsers, the innerHTML attribute is not part of an HTML standard, but rather a proprietary extension originally introduced by Microsoft as part of Internet Explorer. There is no guarantee it will be available in standards-compliant browsers in the future.

Note: in spite of its disadvantages, innerHTML has been shown in some cases to actually run faster than the equivalent DOM code on some browser platforms. If maximum performance is crucial for your application (and you can bear all the disadvantages of innerHTML as detailed above) then you should test the different approaches across all the browsers that your application supports.

DOM methods

In theory there is no need to resort to using the nonstandard innerHTML as there are standards-compliant DOM methods that are capable of the same functionality. For example the above snippet that uses the innerHTML attribute can be rewritten as follows:

	var mydiv = document.getElementById("mydiv");
	var text1 = document.createTextNode("This is the ");
	var boldTag = document.createElement("b");
	var text2 = document.createTextNode("new");	
	boldTag.appendChild(text2);
	var text3 = document.createTextNode(" content of the div");
	while(mydiv.firstChild) {
		  mydiv.removeChild(mydiv.firstChild);
	}
	mydiv.appendChild(text1);
	mydiv.appendChild(boldTag);
	mydiv.appendChild(text3);
				

It should be immediately obvious what the main disadvantage here is compared to the snippet using innerHTML: it takes much more code to do the same (simple) task. We are manipulating the DOM directly and in a standards-compliant way, but we are now responsible for all the various subtasks here: creating the DOM text nodes and appending them to the parent element, creating the 'b' bold tag element and appending its child text node, as well as removing all the existing child elements of the div. We are doing "the right thing" but paying a price for it.

The DCTemplate Approach

To implement the same functionality as the last two examples using DCTemplate, the first step is to create a "template" that looks like this:

	<template name="MyTemplate">This is the <b>new</b> content of the div</template>

Next this template would be "compiled" at the project build time into a JavaScript class called MyTemplate (as specified in the "name" attribute of the template tag above). Then simply call the "render" method of this class to display the content:

	var mydiv = document.getElementById("mydiv");
	var template = new MyTemplate(mydiv);
	template.render();
				

As we can see, this code is much less verbose than the equivalent DOM manipulation code given above, even for such a trivial example. Much larger templates would still use the equivalent of this three line snippet. We also have the advantage of maintaining our template as XML, which, for large templates, is much nicer than putting everything into strings in our JavaScript code.

Other Templating Solutions

Using templates to generate content via JavaScript is not a new concept. There are numerous existing solutions, all of which take slightly different approaches from DCTemplate and one another. The features that make DCTemplate somewhat unique:

  • Templates are "compiled" to executable JavaScript at project build time
  • Geared towards Java/JEE developers, can be used with Apache Maven, or embedded in other Java code
  • Contains constructs to implement looping and conditional execution
  • Templates are well-formed XML files

Downloading DCTemplate

You can grab the latest release of DCTemplate on its Sourceforge download page here.

Running DCTemplate

There are several ways to run DCTemplate: as part of a Maven or ANT build, via the command line, or embedded in other Java code.

Running via Maven

Use the dctemplate-maven plugin to automatically compile templates at project build time:

	<plugin>
		<groupId>org.dctemplate</groupId>
		<artifactId>dctemplate-maven</artifactId>
		<version>1.0</version>
		<executions>
			<execution>
				<phase>compile</phase>
				<goals>
					<goal>dctemplate</goal>
				</goals>
			</execution>
		</executions>
		<configuration>
			<templatePath>${project.basedir}/src/main/webapp/WEB-INF/dctemplates</templatePath>
			<outputPath>${project.basedir}/src/main/webapp/js</outputPath>
		</configuration>
	</plugin>
				

Embedding in Java code

It is very easy to embed DCTemplate in other Java code, simply instantiate the org.dctemplate.core.TemplateRunner class and call the run() method with the path to the input and output locations. For example:

	TemplateRunner runner = new TemplateRunner();
	runner.run("src/templates", "src/js");	
	

Creating Templates

DCTemplate uses a combination of XHTML and a few custom tags to define the actual templates. The current release requires that each template be defined in its own file with a .js.xml file extension. Typically the templates are stored in their own folder in the webapp project, e.g. WEB-INF/dctemplates. The templates must be well formed XML.

In addition to the tags and static content, any valid JavaScript expression can be output using the ${} construct, e.g. ${document.title} will display the title of the current page.

Please see the next section for a full tag reference.

Tag Reference

DCTemplate uses a few custom tags to define the template parameters and provide looping and conditional execution.

<template>

The "template" tag must be the root of the template XML. It defines the file as a template, and takes the following attributes:

  • name: required, specifies the name of the template. This will also be the name of the JavaScript class compiled from the template. To facilitate JavaScript namespaces, dot notation is allowed and encouraged, i.e. org.dctemplate.MyTemplate is a perfectly fine template name.
  • data: optional, a comma separated list of the JavaScript variables this template will take as arguments to its render() method. For instance data="a, b" will produce the method signature render(a, b). These variables can then be used within the template.
Example:
	<template name="MyTemplate" data="person"> 
		Hello, ${person.name}
	</template>				
				

<for>

The "for" tag facilitates repeating certain sections of the template. It takes the following attributes:

  • in: required, unless the "end" attribute is defined; specifies a JavaScript object (array, associative array, etc.) to over which to loop.
  • key: optional, a variable name for the key value in an associative array; must be used with the 'in' attribute.
  • value: optional, a variable name for the array value; must be used with the 'in' attribute.
  • end: required, unless the "in" attribute is defined, ignored otherwise; the condition on which to stop looping; must be a valid JavaScript expression.
  • begin: optional, sets a start condition on the loop; must be a valid JavaScript statement and must be used with the "end" attribute.
  • step: optional, executes on every iteration of the loop; must be a valid JavaScript statement and must be used with the "end" attribute.
Examples:
	<for begin="var index = 0" end="index &lt; 4" step="index++">
		<li>iteration number: ${index}</li>
	</for>
	
	<for key="key" in="map" value="value">
		<li>${key} = ${value}</li>
	</for>
				
				

<if>

The "if" tag allows conditional rendering of part of the template and takes the following attributes:

  • test: required, a valid JavaScript expression; the body of the tag will be processed if the expression evaluates to true

<else>

The "else" tag must be nested within a corresponding "if" tag; the tag body will be processed if the "test" attribute of the "if" tag evaluates to false.

Example Project

The DCTemplate distribution contains a sample project "dctemplate-example" that shows some of the templating functionality in action.

Further Help

Should you have questions or problems that are not addressed in this guide, you can try the Sourceforge DCTemplate help forum here.