In the article where we looked at Handlebars the JavaScript templating engine for the first time, there was a working example, but it was probably not very convincing as to why using Handlebars is much better than concatenating the HTML snippet together in plain JavaScript.

Then there was this example with an Ajax request returning JSON data. There too we used plain JavaScript code but that was already quite unpleasant. Let's now see how can we do the same using Handlebars.

In the earlier example we received a JSON response with the following content:

examples/js/data.json

{
   "title" : "Code Maven",
   "description" : "Coding is fun!",
   "articles" : [
       {
          "title" : "Handling user events in JavaScript",
          "url"   : "http://code-maven.com/handling-events-in-javascript"
       },
       {
          "title" : "On-load counter with JavaScript and local storage",
          "url"   : "http://code-maven.com/on-load-counter-with-javascript-and-local-storage"
       }
   ]
}

We used this code:

examples/js/ajax.js

function ajax_get(url, callback) {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            console.log('responseText:' + xmlhttp.responseText);
            try {
                var data = JSON.parse(xmlhttp.responseText);
            } catch(err) {
                console.log(err.message + " in " + xmlhttp.responseText);
                return;
            }
            callback(data);
        }
    };

    xmlhttp.open("GET", url, true);
    xmlhttp.send();
}

ajax_get('/try/examples/js/data.json', function(data) {
    document.getElementById("title").innerHTML = data["title"];

    var html = "<h2>" + data["title"] + "</h2>";
    html += "<h3>" + data["description"] + "</h3>";
    html += "<ul>";
       for (var i=0; i < data["articles"].length; i++) {
           html += '<li><a href="' + data["articles"][i]["url"] + '">' + data["articles"][i]["title"] + "</a></li>";
       }
    html += "</ul>";
    document.getElementById("text").innerHTML = html;
});


Try it here!

Using Handlebars

The ajax_get function remained the same. It is explained in the article about Ajax request.

The change is in lines 23-25, where instead of concatenating the HTML piece-by-piece, we fetch the template from the text-template tag, compile this template-source into a function called template and then we just pass the data we have received by the Ajax request to this template() function. Much cleaner than earlier when we had to think about using single-quotes outside so they won't interfere with the double-quotes we wanted to use for the HTML attributes.

examples/js/ajax_handlebars.js

function ajax_get(url, callback) {
    xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            console.log('responseText:' + xmlhttp.responseText);
            try {
                var data = JSON.parse(xmlhttp.responseText);
            } catch(err) {
                console.log(err.message + " in " + xmlhttp.responseText);
                return;
            }
            callback(data);
        }
    };

    xmlhttp.open("GET", url, true);
    xmlhttp.send();
}

ajax_get('/try/examples/js/data.json', function(data) {
    document.getElementById("title").innerHTML = data["title"];

    var source   = document.getElementById('text-template').innerHTML;
    var template = Handlebars.compile(source);
    var html    = template(data);

    document.getElementById("text").innerHTML = html;
});



The template itself is located in the HTML file in a script tag.

examples/js/ajax_handlebars.html

<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">
    <h2>{{title}}</h2>
    <h3>{{description}}</h3>
    <ul>
    {{#each articles}}
        <li><a href="{{url}}">{{title}}</a></li>
    {{/each}}
    </ul>
  </script>

<h1 id="title"></h1>
<hr>
<div id="text"></div>

<script src="ajax_handlebars.js"></script>

Try!

The place-holders for {{title}} and {{description}} are simple values that we have already seen in the introduction to Handlebars, but there is also a loop to go over the elements of an array. {{#each articles}} starts a loop on the elements of the array in the articles key. The loop ends when we encounter {{/each}}. Inside the loop we can use the keys of the objects that are the elements of the articles array.

This makes the template much clearer than what we had in the HTML concatenation earlier.