If you do a lot of client-side manipulation of the DOM using JavaScript or jQuery, you might want to consider using one of the many templating engines available. I'm sure you've built some HTML within a string in your JavaScript code. Using string concatenation to build a set of HTML elements leads to hard-to-read and hard-to-debug code. Instead of using string concatenation, take advantage of a templating engine. A templating engine separates the HTML to generate from your code and data, which makes your code easier to read and makes it much easier to locate bugs. As every programmer is aware, separation of concerns (SoC) is a best practice. When you employ SoC in your applications it immediately increases the readability and maintainability of your application. In this article, I'll show you several techniques to make your client-side scripting simpler, easier to read, maintain, and debug.
The Problem with String Concatenation
A simple example to illustrate the issue with using string concatenation is if you wish to dynamically generate an HTML <input>
element with the value
attribute initialized to a movie name, as shown in Figure 1.

Create a file named index.html
in a folder on your hard drive and add the HTML shown in Listing 1. Notice the <div>
element with the id
attribute set to “output”. In the <script>
tag, you're going to write some code to dynamically create an <input>
element with the value from a property inserted into its value
property.
Listing 1: Create a web page to dynamically add an HTML <input>
element.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Using String Concatenation</title>
</head>
<body>
<header>
<h1>Using String Concatenation</h1>
</header>
<main>
<div id="output">
</div>
</main>
<script>
</script>
</body>
</html>
In the <script>
tag, add a window.onload()
function, Listing 2, with an object literal called movie. This movie object contains two properties: filmId
and name
. A method named buildHTML()
is also a part of this object. This method uses string concatenation to create the <input>
element that is insert into the innerHTML
property of the <div id="output">
element. Note that I must break the return statement onto multiple lines for purposes of formatting in this article, however, this must all be on a single line when you type it into your editor.
Listing 2: In the onload() function is where you build the <input>
element.
window.onload = function() {
let movie = {
filmId: 1,
name: "Young Frankenstein",
buildHTML: function() {
return "<input type='text' id='movieName'
name='movieName' value='" + this.name + "' />";
}
};
document.getElementById("output").innerHTML = movie.buildHTML();
};
If you were to type in the code exactly as shown in Listing 2 and display the index page, no <input>
would appear within the <div>
element. Why? Because the closing single quote that surrounds the movie name in the value
attribute is missing. This is a very hard bug to find because you are using string concatenation, and all the single and double quotes are hard to match up, as shown in Figure 2.

There are quite a few problems with using string concatenation. A long line cannot be broken into multiple lines, so you are constantly scrolling horizontally to see the entire line. All the text within the string is a single color, which makes it hard to identify what the different parts of the element are. To add variables into the line, you must use the plus sign (+). Strings in JavaScript are immutable, so the string is constantly being moved to a new location to account for the increase in size. While typing into the string, no IntelliSense is available, so you are relying on your typing skills. If double and single quotes are required within the string, you need to escape one or the other. As you can see, this is a lot of issues when working with string concatenation.
Use Template Literals
Template literals (sometimes called template strings) can solve a couple of the issues with string concatenation. Template literals are delimited with a back tick (`) on each side of the string. If single and double quotes are required within this string, they can be used without escaping those characters. Another advantage is you can split a template literal across multiple lines. This eliminates the amount of horizontal scrolling necessary to see the whole code.
In the buildHTML()
method you wrote previously, modify this code to use a template literal instead of the string concatenation. The return statement now looks like the following code snippet:
"buildHTML": function () {
return `<input type='text' id='movieName' name='movieName'
value='${this.name}' />`;
}
This code snippet may be typed in exactly as shown across multiple lines because this is supported when using template literals. Notice the replaceable token ${this.name}
within the literal. This syntax allows the value from the name
property in the movie object to be placed into this location within the string. If the closing single quote were to be left out, this error would be much easier to see.
What Is a Templating Engine?
A templating engine is like a template literal in that HTML is combined with some replaceable tokens with a variable name into which data from that variable is replaced. What does a replaceable token look like? Each templating engine can have different tokens, but they all usually start with a few characters, have the name to replace, and then end with a few opposite characters. In a template literal, the token was a dollar sign ($), followed by an opening curly brace, then the name of a variable, and closed with a closing curly brace.
Many templating engines use two open curly braces to specify the start of a token, as shown in the following snippet. The property name to be replaced, genre
, is then typed out. The token is closed by using two closing curly braces.
{{genre}}
Other examples of tokens from other templating engines look like the following:
<%= genre %>
{% genre %}
To replace the name genre
with some real data, use a templating engine and send it a JSON object that contains genre
as one of its properties, as shown in the following code snippet:
{
"name": "Young Frankenstein",
"genre": "Comedy"
}
The templating engine performs its magic and replaces the genre
variable in the token with the value of Comedy
from the JSON object. These tokens are typically inserted directly into some HTML, for example:
<input id="genre" name="genre" type="text" value="{{genre}}" />
Build an HTML Project
To truly understand the benefits of using a templating engine, let's build a simple token replacement system using JavaScript. Create a new folder named javascriptSamples
. Under this javascriptSamples folder, create a new folder named scripts
. Add a new file in the scripts folder named common.js
and add the following functions into this file:
function getValue(id) {
return document.getElementById(id).value;
}
function getElement(id) {
return document.getElementById(id);
}
function formatCurrency(value) {
return new Number(value).toLocaleString("en-US",
{ "style": "currency", "currency": "USD" });
}
These functions are just wrappers around some very common JavaScript code. The first function, getValue(id)
, retrieves the value from an element based on the id
you pass in. The second function, getElement(id)
, retrieves the DOM object based on the id
you pass in. The third function, formatCurrency(value)
, takes the value you pass in and returns it formatted as a US currency value.
Create Some Styles
Create a folder named styles
and add a new file in this styles folder named site.css
. Add three CSS rules (Listing 3) to format the label and input elements you're going to use in the samples for this article. The last CSS rule is used to display a movie name from the data input into the movie name field.
Listing 3: Add some styles to make the web page look nicer.
.form-label {
display: inline-block;
min-width: 8em;
margin-bottom: 1em;
}
.form-control {
font-family: inherit;
font-size: 100%;
}
.movieInfo {
display: block;
margin-top: 2em;
font-weight: bold;
font-size: larger;
}
Add a Sample Web Page
Add a file in the javascriptSamples
folder named index.html
. Add the code shown in Listing 4 into this new file. This code displays a form for the entry of a movie name, and a button to click to display the name entered. This movie name will be displayed in a label that's dynamically added to the DOM within the <div id="output">
element.
Listing 4: Create a web page to allow input of a movie name.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Manipulate the DOM Using Templating</title>
<link href="styles/site.css" rel="stylesheet" />
</head>
<body>
<header>
<h1>Manipulate the DOM Using Templating</h1>
</header>
<main>
<div>
<label for="name" class="form-label">Movie Name</label>
<input id="name" name="name" value="Young Frankenstein"
class="form-control" />
</div>
<div>
<label class="form-label"></label>
<button onclick="displayData();">Display Data</button>
</div>
<div id="output"></div>
</main>
<script src="scripts/common.js"></script>
<script>
'use strict';
function displayData() {
}
</script>
</body>
</html>
Try It Out
Display the index.html
file in your browser and it should look like Figure 3. The button does not do anything yet; you'll add that code shortly.

Build a Single Label and Add to DOM Using JavaScript
On the index.html
page, you see a <div>
with its id
attribute set to output.
<div id="output">
</div>
The goal of the displayData()
function is to insert a label into this <div>
with the movie name input into the text box. The <label>
is given the CSS class, movieInfo, so it stands out on the page, as shown in Figure 4. Modify the displayData()
function so it looks like the following:
function displayData() {
// Create a label with the movie name
getElement("output").innerHTML = `<label class='movieInfo'>${getValue("name")}</label>`;
}
The code in the displayData()
function retrieves the <div>
element object and replaces its innerHTML
property with a string. The string is built using a template literal with a <label>
element, the value from the input element with the id
attribute set to name
, and the closing </label>
element.
Try It Out
Display the index.html
file in your browser, enter a name of a movie or take the one already defaulted, and click on the Display Data button. Clicking the button calls the displayData()
function, which builds the <label>
element with the movie name in it. If you have entered everything correctly, your web page should look like Figure 4.

Check for No Input and Display Appropriate Label Using JavaScript
You may wish to ensure that the user entered a movie name into the input element. If they do, display the movie name just like you did in the last example. If they don't enter a movie name, display a message to the user that no movie name was input. Modify the displayData()
function to look Listing 5.
Listing 5: Add some logic to the displayData() function to display an error message if no movie name is entered.
function displayData() {
let html = "";
let name = getValue("name");
if (name) {
html = `<label class='movieInfo'>${name}</label>`;
} else {
html = `<label class='movieInfo'>No Movie Input</label>`;
}
// Add label to div
getElement("output").innerHTML = html;
}
In this function, create a variable named html
into which you build the string to add to the output <div>
. Retrieve the value entered in the input element and place it into a variable called name
. Check to see if name has a value and build the <label>
with the value, or if it doesn't have a value, build the <label>
with the error message. Finally, add the value in the html variable to the innerHTML
property of the <div>
to display the result.
You may be wondering why you're writing this simple code. Later in this article, you are going to perform this type of logic using templating engine tokens to check for true or false values and display two different values based on the result.
Try It Out
Display the index.html
file in your browser, wipe out the movie name and click the Display Data button to see the error message show up, as shown in Figure 5. After doing this, put in a movie name, click the Display Data button, and ensure that the movie name is still displayed.

Build Multiple Labels to Add to DOM Using JavaScript
The code you have written so far in JavaScript hasn't been too bad and is easy to read. However, as you add more elements to the dynamic HTML you want to build, this code can become harder to manage. Open the index.html
file and replace the <main>
element with the HTML shown in Listing 6.
Listing 6: Add more input elements to the web page.
<main>
<div>
<label for="name" class="form-label">Movie Name</label>
<input id="name" name="name" value="Young Frankenstein"
class="form-control" />
</div>
<div>
<label for="rating" class="form-label">Movie Rating</label>
<select id="rating" class="form-control">
<option>G</option>
<option selected>PG</option>
<option>PG-13</option>
<option>R</option>
</select>
</div>
<div>
<label for="genre" class="form-label">Movie Genre</label>
<input id="genre" name="genre" value="Comedy" class="form-control" />
</div>
<div>
<label for="year" class="form-label">Year Released</label>
<input id="year" name="year" value="1974" class="form-control" />
</div>
<div>
<label for="price" class="form-label">Rental Price</label>
<input id="price" name="price" value="3.99" class="form-control" />
</div>
<div>
<label class="form-label"></label>
<button onclick="displayData();">Display Data</button>
</div>
<div id="output"></div>
</main>
Replace the displayData()
function with the code shown in Listing 7. As you can see, the code that builds all the <label>
and <br />
elements is harder to read compared to the previous code. There's more opportunity to miss a closing bracket, or a forward slash because you're mixing code and HTML. Using template literals helps immensely compared to normal string concatenation, but you still don't have color coding or IntelliSense.
Listing 7: Add more code to display more labels.
function displayData() {
let name = getValue("name");
let rating = getValue("rating");
let genre = getValue("genre");
let year = getValue("year");
let price = formatCurrency(getValue("price"));
// Build movie information in labels
let html = `
<label class='movieInfo'>${name}</label>
<label>${rating}</label><br />
<label>${genre}</label><br />
<label>${year}</label><br />
<label>${price}</label><br />
`;
// Add movie labels into <div>
getElement("output").innerHTML = html;
}
Try It Out
Display the index.html
file in your browser, click on the Display Data button, and your page should look like Figure 6.

Use an Object Literal to Add Elements to DOM Using JavaScript
Before you start to learn about template engines, there's one more JavaScript technique you can employ to help make your code even more readable. Use a literal object, named movie, as shown in Listing 8, and populate each property of the object from the data entered. Add a buildHTML()
method into this object to build your string with the <label>
elements to display the movie information.
Listing 8: Use an object literal to wrap up the building of the HTML for the movie data display.
function displayData() {
let movie = {
"name": getValue("name"),
"rating": getValue("rating"),
"genre": getValue("genre"),
"year": getValue("year"),
"price": getValue("price"),
"buildHTML": function () {
return `
<label class='movieInfo'>
${this.name}
</label>
<label>${this.rating}</label><br />
<label>${this.genre}</label><br />
<label>${this.year}</label><br />
<label>${formatCurrency(this.price)}</label><br />`;
}
};
// Add movie labels into <div>
getElement("output").innerHTML = movie.buildHTML();
}
Try It Out
Display the index.html
file in your browser, click on the Display Data button, and your page should still look like Figure 6.
Place HTML to Generate in a Template Element
A literal object makes the JavaScript code easier to read and maintain. However, you're still mixing code and HTML. Since 2015, the HTML language has included a <template>
element that's meant to hold HTML for use with templating engines. Prior to this, developers used the <script>
element to hold this HTML, as shown in the following code snippet.
<script id="template" type="text/html">
<input
id="name"
name="name"
type="text"
value="{{name}}">
</script>
It's recommended to use the <template>
element moving forward, as it semantically helps distinguish between what is script and what is a template of HTML, as shown in the following snippet:
<template id="template" type="text/html">
<input id="name" name="name" type="text" value="{{name}}">
</template>
Using the <template>
element, your editor can now format the HTML and provide color coding (Figure 7). There's no color coding in JavaScript strings to distinguish between code and HTML (Figure 8). In the template, wrap your replaceable items with a token, in this case, {{name}}
, so they can be replaced using JavaScript.


Once the HTML is in a <template>
element, read the innerHTML
property to retrieve the HTML. After reading the HTML with the token in it, search for the token, and replace it with the value from the movie.name
property, as shown in the following code snippet:
window.onload = function() {
let movie = {
filmId: 1,
name: "Young Frankenstein",
buildHTML: function() {
let html = getElement("template").innerHTML;
return html.replace("{{name}}", movie.name);
}
};
getElement("output").innerHTML = movie.buildHTML();
}
If you run this code, you'd have an <input>
on the web page with the value of “Young Frankenstein” in the text box. You now have a nice separation of concerns between the HTML and the code with the data. This is much easier to read, understand, maintain, and debug.
Use a Template Element to Add Multiple Elements to DOM Using JavaScript
Go back to your web project and replace the code in the displayData()
method to use a <template>
element. Just after the closing </main>
tag, add the following code. Assign a unique id
attribute to the <template>
tag. It isn't necessary to add the attribute type to this <template>
tag with the value set to “text/html”. However, I like adding this attribute, as it makes this <template>
element self-documenting.
<!-- Create a template for displaying movie information -->
<template id="template" type="text/html">
<label class="movieInfo">{{name}}</label>
<label>{{rating}}</label> <br />
<label>{{genre}}</label> <br />
<label>{{year}}</label> <br />
<label>{{price}}</label> <br />
</template>
Locate the displayData()
function in the <script>
tag and replace the buildHTML()
method with the code shown below. The first line of code retrieves the HTML from the <template>
element. The succeeding lines of code perform a search and replace on each of the tokens contained in the HTML template.
buildHTML: function () {
// Get the template HTML
let html = getElement("template").innerHTML;
// Perform search and replace on movie info
html = html.replace("{{name}}", this.name);
html = html.replace("{{rating}}", this.rating);
html = html.replace("{{genre}}", this.genre);
html = html.replace("{{year}}", this.year);
html = html.replace("{{price}}", formatCurrency(this.price));
return html;
}
Try It Out
Display the index.html file in your browser, click on the Display Data button, and your page should still look like Figure 6.
Use a Template to Add a Row to a Table Using JavaScript
As another example of using a <template>
element to dynamically add HTML to the DOM, let's build an HTML table from the data entered on the page. Replace the <div id="output">
element on the index page with the following <table>
element:
<table id="movieTable">
<thead>
<tr>
<th>Movie Name</th>
<th>Rating</th>
<th>Genre</th>
<th>Year Released</th>
<th class="pull-end">Price</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Replace the <template>
element with the following HTML. As you enter this HTML, notice how you get IntelliSense to help you enter the elements. You do not get this when you are building a string in JavaScript. Using a <template>
element once again has great advantages over using a string.
<!-- Create a template for a row of movie data -->
<template id="template" type="text/html">
<tr>
<td>{{name}}</td>
<td>{{rating}}</td>
<td>{{genre}}</td>
<td>{{year}}</td>
<td class="pull-end">{{price}}</td>
</tr>
</template>
Because you removed the <div id="output">
and you have a table, you must change the code that adds the results from the buildHTML()
method. Locate these last two lines of code in the displayData()
function.
// Add movie labels into <div>
getElement("output").innerHTML = movie.buildHTML();
Remove those two lines of code and add the following lines to add the HTML as a row of data in the HTML table. This code gets an object reference to the <table>
element. The <tbody>
object reference is retrieved and placed into the body
variable. The insertRow()
method is invoked on the body object passing in the total number of rows in the table. Call the movie.buildHTML()
method to create the HTML and assign that result into the innerHTML
property of the row object.
// Get reference to the table element
let table = document.getElementById('movieTable');
// Get reference to the tbody element
let body = table.getElementsByTagName('tbody')[0];
// Create a blank row
let newRow = body.insertRow(body.rows.length);
// Add Generated HTML to the new row
newRow.innerHTML = movie.buildHTML();
Add Styles for the Table
To make our table look somewhat decent compared to the default table styles the browser uses, add some styles to your project. Open the styles\site.css
file and add the CSS rules shown in Listing 9 into this file.
Listing 9: Add styles for the HTML table.
table {
border-collapse: collapse;
margin-top: 2em;
}
table,
th,
td {
border: 0.02em solid black;
}
table th,
table td {
padding: 0.5em;
}
th {
text-align: left;
}
.pull-end {
text-align: right;
}
Try It Out
Display the index.html
file in your browser, click on the Display Data button, and your web page should look like Figure 9.

Looping to Build a Table
In many applications, you'll be dealing with an array of data that you must load into a table or similar list element. To load a table of HTML data from an array, use the same <template>
and <table>
elements. Remove all the input fields from the <main>
element, and just leave the HTML table, as shown in the following code snippet:
<main>
<table id="movieTable">
<thead>
<tr>
<th>Movie Name</th>
<th>Rating</th>
<th>Genre</th>
<th>Year Released</th>
<th class="pull-end">Price</th>
</tr>
</thead>
<tbody></tbody>
</table>
</main>
Remove the displayData()
function within the <script>
element and add an array, as shown in Listing 10. This array, named movies, contains a collection of movie object literals. Each object literal contains the five properties as the movie object literal used in the previous samples.
Listing 10: Add an array of movie data to the <script>
element.
<script>
'use strict';
let movies = [
{
"name": "2012",
"rating": "PG-13",
"genre": "Action",
"year": "2009",
"price": 3.95
},
{
"name": "9 to 5",
"rating": "PG",
"genre": "Comedy",
"year": "1980",
"price": 2.95
},
{
"name": "African Queen, The",
"rating": "G",
"genre": "Adventure",
"year": "1952",
"price": 3.95
}
];
</script>
Just below this array, and before the closing </script>
tag, add a window.onload()
function, as shown in Listing 11. When this web page is loaded, the onload()
method is called. In this method, retrieve a reference to the table, from which you can get a reference to the <tbody>
element. Also, retrieve the HTML contained in the <template>
element and place that into a variable named template
. Use a foreach()
method to iterate over each element in the movies array. On each iteration, a movie object is placed into the row
variable.
Listing 11: Write code in the window onload() to create an HTML table.
window.onload = function () {
// Get reference to the table element
let table = getElement('movieTable');
// Get reference to the tbody element
let body = table.getElementsByTagName('tbody')[0];
// Get the template HTML
let template = getElement("template").innerHTML;
movies.forEach(row => {
// Assign template to html variable
let html = template;
// Perform search and replace on movie info
html = html.replace("{{name}}", row.name);
html = html.replace("{{rating}}", row.rating);
html = html.replace("{{genre}}", row.genre);
html = html.replace("{{year}}", row.year);
html = html.replace("{{price}}", formatCurrency(row.price));
// Create a blank row
let newRow = body.insertRow(body.rows.length);
// Add Generated HTML to the new row
newRow.innerHTML = html;
});
}
For each row in the array, assign to a variable named html
the HTML from the template
variable. Take the data from the row
variable and replace each property into the appropriate token contained in the template. This is similar code to that created when loading a single row into the table. Insert a blank row at the end of the rows in the <tbody>
and insert the HTML generated from the current movie object into this new row. After all objects have been created, the HTML table is built and should look like Figure 10.

Try It Out
Display the index.html
file in your browser to see the HTML, as shown in Figure 10.
The Mustache.js Templating Engine
To illustrate a templating engine, I'm going to use Mustache.js. Mustache.js
is a JavaScript library that became the standard for most other templating engines. Check out Mustache at https://github.com/janl/mustache.js. You may wonder why it's called mustache. It's because the tag or token delimiters are curly braces. Rotate the opening curly brace 90 degrees to the right and it looks like a mustache. Mustache is what's known as a logic-less template syntax. Mustache doesn't contain any if, else, or looping statements; there are only tokens. When you read the mustache documentation, they refer to {{name}}
as a tag. I prefer to use the name token, as in HTML, you already have a tag such as the <template>
tag.
Build an HTML Project Using Mustache
Create a new folder to place the samples for working with Mustache. Keep these new samples separate from the JavaScript samples previously created so you can compare the two side-by-side. Create a new folder named mustacheSamples
. Copy the folder named scripts
from the javascriptSamples
folder into the mustacheSamples
folder. Copy the styles
folder from the javascriptSamples
folder into the mustacheSamples
folder. You now need to get the mustache.js
library onto your computer so you can copy it into the scripts folder in the mustacheSamples
folder.
Install mustache.js Using Node Package Manager (npm)
If you have npm installed on your computer, create a directory on your computer named mustache
. Open a command window in the new mustache
folder and execute the following command:
npm install mustache –save
After running this command, you'll find the mustache.min.js
file located in the \mustache\node_modules\mustache
folder. Copy that file into the scripts folder in the mustacheSamples
folder.
Install mustache.js by Downloading from GitHub
If you do not have npm on your computer, you can download the mustache.min.js
file from my GitHub folder located at https://github.com/PaulDSheriff/Training-Samples/tree/main/mustacheJS. Download the mustache.min.js
file to the scripts folder in the mustacheSamples
folder.
Create the Index Page
Create an index.html
file in the mustacheSamples
folder and add the HTML shown in Listing 12. This HTML should look familiar, as it's almost identical to the index.html
file first created in this article. The major difference is the reference to the mustache.min.js
file.
Listing 12: Create an index page that uses the mustache.js templating engine.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Manipulate the DOM Using Templating</title>
<link href="styles/site.css" rel="stylesheet" />
</head>
<body>
<header>
<h1>Manipulate the DOM Using Templating</h1>
</header>
<main>
<div>
<label for="name" class="form-label">Movie Name</label>
<input id="name" name="name" value="Young Frankenstein"
class="form-control" />
</div>
<div>
<label class="form-label"></label>
<button onclick="displayData();">Display Data</button>
</div>
<div id="output"></div>
</main>
<script src="scripts/mustache.min.js"></script>
<script src="scripts/common.js"></script>
<script>
'use strict';
function displayData() {
}
</script>
</body>
</html>
Try It Out
Display the index.html
page in your browser and it should look like Figure 3.
Build a Single Label and Add to DOM Using Mustache
In the index.html
file, just after the closing </main>
tag, add a <template>
element. Into this <template>
element, you add the label into which you will take the value entered and replace that value into the {{name}}
token.
<!-- Create a template for displaying movie information -->
<template id="template" type="text/html">
<label class="movieInfo">
{{name}}
</label>
</template>
Modify the displayData()
function to read the HTML from this <template>
element and send it to the Mustache engine for replacing the tokens with data. The global Mustache object is defined in the mustache.min.js
file and has a render()
method. The render()
method accepts two arguments; the template string, and an object literal. The object literal contains properties with the same name as those used in each token. Mustache takes care of performing searches for each token and replacing it with data from the object literal. No need to call the individual replace()
methods to build the HTML;
Mustache takes care of that for you. As you can see, this is greatly simplified code from what you used to write.
Try It Out
Display the index.html
file in your browser, enter a name of a movie or take the one already defaulted, and click on the Display Data button. Clicking the button calls the displayData()
function that uses Mustache to build the web page that looks like Figure 4.
Check for Truthy Expressions Using a Section
In addition to tokens that render a single value, mustache also has tags called sections. A section tag starts with {{#name}}
and the section ends with {{/name}}
. Placing a pound-sign (#) before the name informs mustache to check if the value in the property name
has a value. If the value is null or empty, a false
is returned from this section, and everything between the section tokens is not rendered. Think of this as an if statement and only if the value is true
does everything between these section tokens get rendered. Replace the <template>
element in the index.html
file with the following template.
<template id="template" type="text/html">
{{#name}}
<label class="movieInfo">
{{name}}
</label>
{{/name}}
</template>
Try It Out
Display the index.html
file in your browser, delete the movie name in the text box, and click on the Display Data button and nothing is displayed in the output area because the <label>
element is never rendered.
Check for Falsy Expressions Using an Inverted Section Tag
Another kind of section tag is called an inverted section. These sections begin with {{^name}}
and the section ends with {{/name}}
. The up-caret symbol (^) informs mustache to check the value in the property name
and invert the value. If the name
property has a value, return false
, and if it doesn't have a value, return true
. Replace the <template>
element in the index.html
file with the following template.
<template id="template" type="text/html">
{{^name}}
<label class="movieInfo">
No Movie Input
</label>
{{/name}}
</template>
Try It Out
Display the index.html
file in your browser, delete the movie name in the text box and click on the Display Data button and it should look like Figure 5. Put a movie name into this text box, and nothing is displayed.
Combine Section Tags in a Template
If you combine the use of both these section tags in a template, it effectively becomes an if…else statement. For example, replace the <template>
element with the following snippet's HTML and tokens. A <label>
element is to appear regardless of the user input, so both section tags go within the <label>.
However, only one value is displayed depending on whether some data is entered or not.
<template id="template" type="text/html">
<label class="movieInfo">
{{#name}}{{name}}{{/name}}
{{^name}}No Movie Input{{/name}}
</label>
</template>
Try It Out
Display the index.html
file in your browser, with a movie name in the text box click on the Display Data button. The movie name should appear on your web page. Delete the movie name from the text box and click on the Display Data button to see the error message No Movie Input appear.
Build Multiple Elements and Add to DOM
Now that you're used to working with Mustache tokens and section tags, let's go back to the code where you're working with multiple elements. This is where you really see how much less code you must write. Replace the <main>
element with the code shown in Listing 13.
Listing 13: Add multiple input elements to the HTML page.
<main>
<div>
<label for="name" class="form-label">Movie Name</label>
<input id="name" name="name" value="Young Frankenstein"
class="form-control" />
</div>
<div>
<label for="rating" class="form-label">Movie Rating</label>
<select id="rating" class="form-control">
<option>G</option>
<option selected>PG</option>
<option>PG-13</option>
<option>R</option>
</select>
</div>
<div>
<label for="genre" class="form-label">Movie Genre</label>
<input id="genre" name="genre" value="Comedy"
class="form-control" />
</div>
<div>
<label for="year" class="form-label">Year Released</label>
<input id="year" name="year" value="1974"
class="form-control" />
</div>
<div>
<label for="price" class="form-label">Rental Price</label>
<input id="price" name="price" value="3.99"
class="form-control" />
</div>
<div>
<label class="form-label"></label>
<button onclick="displayData();">Display Data</button>
</div>
<div id="output"></div>
</main>
Locate the <template>
element and replace the contents with the following HTML and tokens. If you're working in VS Code or similar editor, notice how nice it is to get IntelliSense and color coding while building this template.
<template id="template" type="text/html">
<label class="movieInfo">
{{#name}}{{name}}{{/name}}
{{^name}}No Movie Input{{/name}}
</label>
<label>{{rating}}</label><br />
<label>{{genre}}</label><br />
<label>{{year}}</label><br />
<label>{{price}}</label><br />
</template>
Modify the displayData()
function to build a movie object literal and populate each property with the data input by the user (Listing 14). Notice that you don't need to write a buildHTML()
method, you only need to populate the individual properties. Using Mustache reduces the code needed and provides the separation of concerns discussed earlier.
Listing 14: Read all data from the input elements and use Mustache to generate the HTML.
function displayData() {
let movie = {
"name": getValue("name"),
"rating": getValue("rating"),
"genre": getValue("genre"),
"year": getValue("year"),
"price": getValue("price")
};
// Read template with Mustache tokens
let tmpl = getElement("template").innerHTML;
// Use Mustache to render the HTML
let html = Mustache.render(tmpl, movie);
// Add the rendered HTML to the div
getElement("output").innerHTML = html;
}
Try It Out
Display the index.html
file in your browser, click on the Display Data button and the resulting web page should look almost like Figure 6.
Display Price as Currency Value
Notice on your web page that the price
value is not displayed in a U.S. currency format. This is because you didn't use the formatCurrency()
function when putting the input value into the price
property. I'd suggest that you read the data directly from the inputs and place those values directly into the properties. If you send this data to a back-end, you most likely want to store the raw numbers without any currency symbols.
To handle these types of situations, create a method on your literal object that transforms your property into the appropriate string for display. For example, for the price
property, create a priceFormatted()
method that returns the price
property formatted as a U.S. currency, as shown in the following code snippet:
let movie = {
name: getValue("name"),
rating: getValue("rating"),
genre: getValue("genre"),
year: getValue("year"),
price: getValue("price"),
priceFormatted: function() {
return formatCurrency(this.price);
}
};
Modify the <template>
to display priceFormatted
instead of price
, as shown in the following code snippet. The Mustache rendering engine looks at each token name and determines if it's a simple property or a function, and makes the appropriate call for replacement into that token.
<template id="template" type="text/html">
<label class='movieInfo'>
{{#name}}{{name}}{{/name}}
{{^name}}No Movie Entered{{/name}}
</label>
<label>{{rating}}</label><br />
<label>{{genre}}</label><br />
<label>{{year}}</label><br />
<label>{{priceFormatted}}</label><br />
</template>
Try It Out
Display the index.html
file in your browser, click on the Display Data button, and it should now look exactly like Figure 6.
Build a Select List Using Templating
Section tags, besides checking for true or false, also check a property to see if it's a list. Each item of the list is iterated over and the tokens specified within the template are replaced. Create a new HTML file named select-list.html
and add the HTML shown in Listing 15 into this file. Notice the <select>
element with the id
set to “movies”. In this <select>
is where <option>
elements are added to create a drop-down list of movies.
Listing 15: Create a web page to render a select list.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Templating a Select List</title>
<link href="styles/site.css" rel="stylesheet" />
</head>
<body>
<header>
<h1>Templating a Select List</h1>
</header>
<main>
<select id="movies"></select>
</main>
<script src="scripts/mustache.min.js"></script>
<script src="scripts/common.js"></script>
<script>
</script>
</body>
</html>
Add the code shown in Listing 16 into the empty <script>
element. This code creates a simple list of data in an object literal named movies. This object literal has a single array property named movieList
. Each element of this array is another object literal with two properties: filmId
and name
. Each of these properties is used to create the <option>
elements in the <select>
element.
Listing 16: Add a movie list and the code to render this list into the select list.
<script>
'use strict';
window.onload = function () {
let movies = {
"movieList": [
{
filmId: 1,
name: "Casablanca"
},
{
filmId: 2,
name: "Caddy Shack"
},
{
filmId: 3,
name: "Young Frankenstein"
}
]
};
// Read template with Mustache tokens
let tmpl = getElement("template").innerHTML;
// Use Mustache to render the HTML
let html = Mustache.render(tmpl, movie);
// Add the rendered HTML to the select
getElement("movies").innerHTML = html;
};
</script>
Just after the closing </main>
tag, add a <template>
element, as shown in the following code snippet. Within the section {{#movieList}}
is the HTML needed to build each <option>
element from the filmId
and name
properties. The section tag needs to be the same name as the array property within the movies object literal, in this case movieList
.
<!-- Create a Mustache Template -->
<template id="selectTemplate" type="text/html">
{{#movieList}}
<option value="{{filmId}}">
{{name}}
</option>
{{/movieList}}
</template>
Try It Out
Display the select-list.html
file in your browser and you should see a drop-down list of movie names, as shown in Figure 11.

Build a Table Using Templating
If several properties of an object literal in an array are needed to display on an HTML page, a <table>
element is ideally suited for this. Create a new folder named classes
and add a new file named Movies.js
into this new folder. Add the code shown in Listing 17 to the Movies.js
file.
Listing 17: Create a closure that provides a list of movie data.
class Movies {
// Private fields
#list = [];
// Public properties
get movieList() {
return this.#list;
}
// Public Methods
getAll() {
this.#list = [
{
"filmId": 1,
"name": "2012",
"genres": "Action,Adventure,Sci-Fi",
"actors": "John Cusack,Amanda Peet",
"runTimeInMinutes": 158,
"rating": "PG-13",
"price": 3.95,
"releaseDate": "2009-11-13"
},
{
"filmId": 2,
"name": "9 to 5",
"genres": "Comedy",
"actors": "Jane Fonda,Lily Tomlin,Dolly Parton",
"runTimeInMinutes": 109,
"rating": "PG",
"price": 2.95,
"releaseDate": "1980-12-19"
},
{
"filmId": 5,
"name": "African Queen, The",
"genres": "Adventure,Drama,Romance",
"actors": "Humphrey Bogart,Katharine Hepburn",
"runTimeInMinutes": 105,
"rating": "G",
"price": 3.95,
"releaseDate": "1952-02-20"
},
{
"filmId": 6,
"name": "Alien",
"genres": "Horror,Sci-Fi",
"actors": "Sigourney Weaver",
"runTimeInMinutes": 117,
"rating": "R",
"price": 3.95,
"releaseDate": "1979-05-25"
}
];
}
}
In the Movie.js
file, you create a Movies class using the class keyword. A single private field named #list
is created to hold the data created in the getAll()
method. A single public property named movieList
is created to return the array of movie data contained in the #list
field. This class is going to be used to populate the <table>
in the next web page you are creating.
Create a Page to Display the Table
Create a new HTML file named table.html
and add the HTML shown in Listing 18 into this new file. The <table>
element has an id
attribute set to "movieTable"
. Into the empty <tbody>
element is where each row of movie data is to be inserted. Be sure to include the Movies.js
script file in your HTML page.
Listing 18: Create a web page to display a table of movie data.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Templating an HTML Table</title>
<link href="styles/site.css" rel="stylesheet">
</head>
<body>
<header>
<h1>Templating an HTML Table</h1>
</header>
<main>
<table id="movieTable">
<thead>
<tr>
<th>Movie Name</th>
<th>Actors</th>
<th>Genres</th>
<th class="pull-end">Rental Price</th>
<th>Run Time</th>
<th>Release Date</th>
</tr>
</thead>
<tbody></tbody>
</table>
</main>
<script src="scripts/mustache.min.js"></script>
<script src="scripts/common.js"></script>
<script src="classes/Movies.js"></script>
<script>
</script>
</body>
</html>
Add the code shown in Listing 19 into the empty <script>
element. This code creates a new instance of the Movies class and assigns it to a variable named entity
. The getAll()
method is invoked on the entity object to load all the movie data into the private #list
field. A literal object named vm is created to wrap up the list of movies and to provide additional methods used to format the movie data when displayed in the table.
Listing 19: Create the table from the Movies class and the template in this page.
<script>
'use strict';
window.onload = function() {
// Create instance of class
let entity = new Movies();
// Load all movies into the movieList property
entity.getAll();
// Create a view model
let vm = {
//"movieList": null,
"movieList": entity.movieList,
"priceFormatted": function() {
return formatCurrency(this.price);
},
"runTime": function() {
let value = new Number(this.runTimeInMinutes);
let hours = Math.floor(value / 60);
let minutes = value % 60;
return `${hours} hours and ${minutes} minutes`;
}
};
// Read template with Mustache tokens
let tmpl = getElement("template").innerHTML;
// Use Mustache to render the HTML
let html = Mustache.render(tmpl, vm);
// Add the rendered HTML into the table
getElement("movieTable").getElementsByTagName(
"tbody")[0].innerHTML = html;
};
</script>
Just below the closing </main>
tag, add a new <template>
element with one section to build the row of movie data (Listing 20). The inverted section is for when there are no movies and you wish to display a message to the user.
Listing 20: Use two section tags to display an error when there is no movie data or to display the list of movies.
<!-- Template to Build a Table -->
<template id="template" type="text/html">
{{#movieList}}
<tr>
<td>{{name}}</td>
<td>{{actors}}</td>
<td>{{genres}}</td>
<td class="pull-end">{{priceFormatted}}</td>
<td>{{runTime}}</td>
<td>{{releaseDate}}</td>
</tr>
{{/movieList}}
{{^movieList}}
<tr>
<td colspan="6">** No Movies Available **</td>
</tr>
{{/movieList}}
</template>
Try It Out
Display the table.html
file in your browser and it should look like Figure 12.

Go back to the vm object literal and uncomment the line that sets the movieList
property to null. Comment out the other movieList
property that's assigned data from the entity.movieList
property. Display the table.html
file again in your browser and you should now see the error message appear, as shown in Figure 13.

Other Templating Engines
There are many different templating engines for use on web pages. Some of the more common ones are handlebars, pug, EJS, Ember, and Vue. The syntax is similar to what you learned in this article, although the delimiters used for their tokens may be a little different. Many of these engines have more features than Mustache; however, check to make sure you need all those features before you add the extra library size to your web project. If you're already using jQuery in your web pages, you might want to explore jQuery Templates.
Are Templating Engines Still Relevant?
With the advent of JavaScript frameworks such as Angular, Vue, and React, are templating engines like Mustache even needed anymore? I think they still serve a purpose if you're focusing mainly on client-side code calling Web APIs. Templating engines are also used to build websites with node.js and Express. In a future article, I'll explore creating a website using node.js, Express, and a templating engine.
Summary
Use templates whenever you find yourself embedding HTML inside of JavaScript strings. Whether you code the search and replace yourself, or use a templating engine like Mustache, take advantage of the <template>
element to store your HTML. Using templating engines makes it much easier to create dynamic web pages while making your code more maintainable and readable. Other benefits include separation of concerns, the ability to get IntelliSense when typing in your HTML, color coding, and code that's easier to debug.