Modern web applications use DOM manipulation to dynamically change areas of the page or insert values. A typical example is a table of figures; the initial page could return HTML column headers then initialize an Ajax request which returns several data records. The data is then appended to the table — but how? The developer has two choices:
- JavaScript is used to build HTML row strings or DOM fragments which are appended to the table. That seems easy until you need to make a change and must hunt around your JavaScript for the associated HTML code. To make life simpler, developers often return whole HTML string fragments from the Ajax call, but that makes the payload more verbose and opens the potential for Cross-Site Scripting attacks.
- Alternatively, you create an empty first row in the HTML page which is used as a template for all other rows. That should be easier to maintain, but you’ll need to remove it from the DOM or style it with display:none to ensure it doesn’t appear.
Neither solution is particularly elegant.
Fortunately, the W3C has introduced a new template
tag which provides a mechanism to define HTML markup fragments as prototypes. (Perhaps it will also appease those upset by the demise of the hgroup element!)
In essence, a template can be used to insert fragments of HTML code into your page, e.g.
<template id="mytablerow">
<tr>
<td class="record"></td>
<td></td>
<td></td>
</tr>
</template>
The template
code can be defined almost anywhere — the head
, body
or even a frameset
. However:
- templates will not display
- templates are not considered to be part of the document, i.e. using document.getElementById(“mytablerow”) will not return child nodes
- templates are inactive until used, i.e. enclosed images will not download, media will not play, scripts will not run, etc.
Using templates
To use a template, it must be cloned and inserted into the DOM. For example, assuming the following HTML:
<table id="mytable">
<thead>
<tr>
<td>ID</td>
<td>name</td>
<td>twitter</td>
</tr>
</thead>
<tbody>
<!-- rows to be appended here -->
</tbody>
</table>
<!-- row template -->
<template id="mytablerow">
<tr>
<td class="record"></td>
<td></td>
<td></td>
</tr>
</template>
We can clone a new row in JavaScript:
// fetch tbody and row template
var t = document.querySelector("#mytable tbody"),
row = document.getElementById("mytablerow");
// modify row data
var td = row.getElementsByTagName("td");
td[0].textContent = "1";
td[1].textContent = "SitePoint";
td[2].textContent = "sitepointdotcom";
// clone row and insert into table
t.appendChild(row.content.cloneNode(true));
The important question: can we use template tags?
Probably not just yet. It’s supported in the latest version of Chrome and Firefox nightlies. Opera will support the tag when it switches to Blink. No word from the IE and Safari teams yet, but a template shim has been demonstrated on JSfiddle should you wish to support all browsers.
Personally, I think the template
tag is a great idea. It’s simple and standardizes templating techniques for HTML5 developers.