Constructing HTML with templates
Using JavaScript makes it possible to dynamically add and remove HTML content in the browser.
This article shows an approach to adding HTML content that is common, but results in poor readability. It then gradually modifies the code to introduce templates as a better way to generate and display new HTML content.
Constructing elements with jQuery
Using jQuery is an easy way to create a new HTML element in JavaScript. After creating the element you can add it to the page:
var title = "Constructing HTML Elements";
var container = $("<div>");
container.addClass("tutorial");
var h1 = $("<h1>");
h1.text(title);
h1.addClass("tutorial-heading");
container.append(h1);
$("body").append(wrapper);
The code above adds this to the body element in your HTML:
<div class="tutorial">
<h1 class="tutorial-heading">Constructing HTML Elements</h1>
</div>
Using jQuery to construct new elements is easy, but it has several downsides.
Most importantly, while it's easy to write this code it's hard to read it. There's no separation between the HTML and the JavaScript code.
You also need a lot of JavaScript code to generate 3 lines of HTML.
There's one positive thing to note about the code above. By creating a variable called title
it separates your HTML structure from the data that's displayed inside it. This makes it easy to re-use this code when you want to display a different article.
Generating an HTML string
Constructing a string that contains the HTML code is a better approach. You can then append that string to the body:
var title = "Constructing HTML Elements";
var html = [
'<div class="tutorial">',
'<h1 class="tutorial-heading">' + title + '<h1>',
'</div>'
].join("\n");
// html: '<div ...>\n<h1 ...>Constructing HTML Elements<h1>\n</div>'
$("body").append(html);
This code begins to separate the HTML from the JavaScript.
Since JavaScript doesn't support multi-line strings we're using the join
method to connect the 3 strings in the list together using a line break (\n
).
Using template libraries
Template libraries help further break apart JavaScript and HTML code by letting you use placeholders inside your HTML string.
A popular JavaScript templating library is Mustache:
var data = {
title: "Constructing HTML Elements"
}
var template = [
'<div class="tutorial">',
'<h1 class="tutorial-heading">{{title}}<h1>',
'</div>'
].join("\n");
// template: '<div ...>\n<h1 ...>{{title}}<h1>\n</div>'
var html = Mustache.render(template, data);
$("body").append(html);
You can try this example on jsFiddle.
Mustache allows us to use {{title}}
as a placeholder inside the HTML string.
We then call Mustache.render
and pass in the data object that contains the values for our placeholders. Mustache then looks up title
in the data object and uses it to replace {{title}}
in the template.
Moving the HTML out of the JavaScript file
Currently, our HTML template is constructed inside the JavaScript file. That has two downsides:
- We need to wrap the HTML code in quotes to generate strings
- Mixing HTML and JavaScript makes the application less well-structured
There's a way to store arbitrary text in your initial HTML page download. We can use this mechanism to store our template string.
If you create a script tag with a type the browser doesn't understand the browser won't attempt to run what's inside it.
For example if you set type to "text/template", then you can embed your HTML template in the script tag, but the HTML won't become visible:
<script id="tutorial-template" type="text/template">
<div class="tutorial">
<h1 class="tutorial-heading">{{title}}<h1>
</div>
</script>
We can then take the contents of our script tag and store it in the template
variable:
var data = {
title: "Constructing HTML Elements"
}
var template = $("#tutorial-template").html();
// html: '<div ...>\n<h1 ...>{{title }}<h1>\n</div>'
var html = Mustache.render(template, data);
$("body").append(html);
To access the template we select the script tag by its ID and use jQuery's html
function to access the embedded HTML code.
Now the HTML template and the JavaScript code are fully separated. Try the code here.
Storing each template in a separate file
The example above works quite well, and makes it easy to further improve your code later.
However, inserting your templates in the main HTML file can get messy if you have a large number of templates.
Another downside is that your editor's syntax highlighting may not work on the template code because it's inside a script tag.
Ideally, each template would have its own file and you would use a tool like grunt-html-convert to access the templates from your JavaScript code.
It's a bit more complex to set this up though, and not necessarily required for a small application. If you're just beginning to build JavaScript apps putting the template in a script tag is good enough.