Introduction to Handlebars, the JavaScript templating system
In the article about input and output with JavaScript you could see the the problem of creating HTML snippet on-the-fly to be included in the rest of the page.
Handlebars is a templating system for JavaScript that provides help to reduce anxiety over the creation of such pages.
Let's convert the plain JavaScript example to use Handlebars.
Pure JavaScript version
This is the example from the input and output with JavaScript article:
examples/js/pure_js_greating.html
<html> <head> <title>Hello World</title> </head> <body> First name: <input id="first_name"> Last name: <input id="last_name"> <button id="say">Say hi!</button> <hr> <div id="result"></div> <script> function say_hi() { var fname = document.getElementById('first_name').value; var lname = document.getElementById('last_name').value; var html = 'Hello <b>' + fname + '</b> ' + lname; document.getElementById('result').innerHTML = html; } document.getElementById('say').addEventListener('click', say_hi); </script> </body> </html>Try!
Switching to Handlebars
This is the solution using Handlebars:
examples/js/handlebars_greating.html
<html> <head> <title>Hello World</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.1/handlebars.min.js"></script> <script id="text-template" type="text/x-handlebars-template"> Hello <b>{{first_name}}</b> {{last_name}} </script> </head> <body> First name: <input id="first_name"> Last name: <input id="last_name"> <button id="say">Say hi!</button> <hr> <div id="result"></div> <script> function say_hi() { var fname = document.getElementById('first_name').value; var lname = document.getElementById('last_name').value; var source = document.getElementById('text-template').innerHTML; var template = Handlebars.compile(source); var context = {first_name: fname, last_name: lname}; var html = template(context); document.getElementById('result').innerHTML = html; } document.getElementById('say').addEventListener('click', say_hi); </script> </body> </html>Try!
In order to use Handlebars, first we need to load the Handlebars library. We can use it directly from CDN JS:
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.1/handlebars.min.js"></script>
or we could download the same file to our server and load it from there.
We create an HTML snippet and put place holders in double curly braces in it:
Hello <b>{{first_name}}</b> {{last_name}}
We can deliver the template to the HTML in several ways, but one of the recommended ways is to embed it in the head of the HTML file withing script tags with a unique id. This way we can easily include several templates and it is much clearer how we would like the final HTML to look like.
<script id="text-template" type="text/x-handlebars-template"> Hello <b>{{first_name}}</b> {{last_name}} </script>
Then we arrive to JavaScript part. In the JavaScript code we replaced the single line combining the content of fname, lname with some HTML that looked like this:
var html = 'Hello <b>' + fname + '</b> ' + lname;
with new code:
var source = document.getElementById('text-template').innerHTML; var template = Handlebars.compile(source); var context = {first_name: fname, last_name: lname}; var html = template(context);
I know, it looks more complex than we had earlier, and indeed in such a simple case when we only need to embed the content of two varaibles in a simple HTML snippet, this might be overengineering, but as your application grows you'll see that the complexity of the pure JavaScript version would increase while for Handlebar, basically that's the whole complexity.
Let's go over those 4 lines.
In the first line we access the script element with the id text-template where we put the template and using innerHTML we copy its content to the variable called source.
In the second line we compile this template and create a Handlebars object using the Handlebars.compile() method. Actually what the compile method returns is a function that we'll call later.
In the third line we create a mapping from keys that will match the place holders to the values that will replace the place holders. These are the values we got from the input elements. This is just a plain JavaScript object. Nothing special. (You'd call it a hash, associated array or dictionary depending on which other language you are familiar with.)
Finally we ask the template to replace the place holders by the respective values and assign the generated string to the variable html
After that we can go back to what we also had in the plain JavaScript code and embed the new HTML in the existing DOM using
document.getElementById('result').innerHTML = html;
That's it about the basics of Handlebars. If you'd like to learn more, you can check out the documentation on the web site of Handlebars
Comments
Hello!! Your article is excellent it has provided me with good information. I need your help in solving one problem I am using handlebarjs for templating. I have three templates in one single file and a singal json object (ie array of objects within array of objects) depending on the condition in one of my helper function i am trying to nest a template into parent template. I can share the piece of code with you.
Published on 2015-03-31