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 < 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.
|