The <template>
HTML element is a mechanism for holding HTML that is not to be rendered immediately when a page is loaded but may be instantiated subsequently during runtime using JavaScript.
Think of a template as a content fragment that is being stored for subsequent use in the document. While the parser does process the contents of the <template>
element while loading the page, it does so only to ensure that those contents are valid; the element's contents are not rendered, however.
This element only includes the global attributes.
However, the HTMLTemplateElement
has a content
property, which is a read-only DocumentFragment
containing the DOM subtree which the template represents. Note that directly using the value of the content
could lead to unexpected behavior, see Avoiding DocumentFragment pitfall section below.
First we start with the HTML portion of the example.
<table id="producttable">
<thead>
<tr>
<td>UPC_Code</td>
<td>Product_Name</td>
</tr>
</thead>
<tbody>
</tbody>
</table>
<template id="productrow">
<tr>
<td class="record"></td>
<td></td>
</tr>
</template>
First, we have a table into which we will later insert content using JavaScript code. Then comes the template, which describes the structure of an HTML fragment representing a single table row.
Now that the table has been created and the template defined, we use JavaScript to insert rows into the table, with each row being constructed using the template as its basis.
if ('content' in document.createElement('template')) {
var tbody = document.querySelector("tbody");
var template = document.querySelector('#productrow');
var clone = template.content.cloneNode(true);
var td = clone.querySelectorAll("td");
td[0].textContent = "1235646565";
td[1].textContent = "Stuff";
tbody.appendChild(clone);
var clone2 = template.content.cloneNode(true);
td = clone2.querySelectorAll("td");
td[0].textContent = "0384928528";
td[1].textContent = "Acme Kidney Beans 2";
tbody.appendChild(clone2);
} else {
}
The result is the original HTML table, with two new rows appended to it via JavaScript:
A DocumentFragment
is not a valid target for various events, as such it is often preferable to clone or refer to the elements within it.
Consider the following HTML and JavaScript:
<div id="container"></div>
<template id="template">
<div>Click me</div>
</template>
const container = document.getElementById("container");
const template = document.getElementById("template");
function clickHandler(event) {
event.target.append(" — Clicked this div");
}
const firstClone = template.content.cloneNode(true);
firstClone.addEventListener("click", clickHandler);
container.appendChild(firstClone);
const secondClone = template.content.firstElementChild.cloneNode(true);
secondClone.addEventListener("click", clickHandler);
container.appendChild(secondClone);
firstClone
is a DocumentFragment instance, so while it gets appended inside the container as expected, clicking on it does not trigger the click event. secondClone
is an HTMLDivElement instance, clicking on it works as one would expect.