Handlebars.js is a popular templating engine that is powerful, simple to use and has a large community. It is based on the Mustache template language, but improves it in several important ways. With Handlebars, you can separate the generation of HTML from the rest of your JavaScript and write cleaner code.

This quick article is an attempt to teach you almost everything you need to know about Handlebars in 10 minutes or less. It may seem a bit overwhelming in the beginning, but just like riding a bike (pun intended), after you get the hang of it, it becomes the easiest thing in the world.

0. Adding it to your project

Adding handlebars to your project is pretty straightforward. Just go to http://handlebarsjs.com/ , and click the download button to get the latest version. At the moment of writing, this is version 2.0.0. Now all you have to do is to include the library in your html with a regular <script> tag.

You can also use a CDN-hosted version, which has the added benefit that the same file might be cached already in the visitor's browser, if it has been used by another website.

// From File
<script src="handlebars-v2.0.0.js"></script>

// From CDN
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.js"></script>

1. Templates

Once you have the library in place, you can start writing templates. The recommended way of adding templates to your page is by including them in <script> tags with a special type. The type attribute is important, otherwise the browser will attempt to parse them as JavaScript (which they are not).

The templates have an easy to grasp syntax. They can contain HTML and text, mixed with Handlebars expressions. Expressions are wrapped in double or triple curly braces {{}}. Expressions tell Handlebars to include the value of variables or to execute helper functions. Templates need to be compiled to a JavaScript function before use. You can see an example below. Note that we are using jQuery to make working with the DOM easier, but Handlebars can work perfectly without it.

<!--This is our template. -->
<!--Data will be inserted in its according place, replacing the brackets.-->
<script id="address-template" type="text/x-handlebars-template">
  <p>You can find me in {{city}}. My address is {{number}} {{street}}.</p>
</script>

<!--Your new content will be displayed in here-->
<div class="content-placeholder"></div>
$(function () {
  // Grab the template script
  var theTemplateScript = $("#address-template").html();

  // Compile the template
  var theTemplate = Handlebars.compile(theTemplateScript);

  // Define our data object
  var context={
    "city": "London",
    "street": "Baker Street",
    "number": "221B"
  };

  // Pass our data to the template
  var theCompiledHtml = theTemplate(context);

  // Add the compiled html to the page
  $('.content-placeholder').html(theCompiledHtml);
});

 

2. Expressions

To build up from the previous example, any data that you print out in an {{ }} expression, will automatically get HTML escaped by handlebars. This is a great security feature, but some times you might wish to print raw HTML. In this case you will use the triple curly brace expression {{{ }}}.

Also, notice that the handlebars expressions support nested values which enables us to easily access any data from a JavaScript object.

<script id="expressions-template" type="text/x-handlebars-template">
  {{description.escaped}}
  {{example}}

  <br><br>

  {{description.unescaped}}
  {{{example}}}
</script>

<div class="content-placeholder"></div>
$(function () {
  // Grab the template script
  var theTemplateScript = $("#expressions-template").html();

  // Compile the template
  var theTemplate = Handlebars.compile(theTemplateScript);

  // Define our data object
  var context={
    "description": {
      "escaped": "Using {{}} brackets will result in escaped HTML:",
      "unescaped": "Using {{{}}} will leave the context as it is:"
    },
    "example": "<button> Hello </button>"
  };

  // Pass our data to the template
  var theCompiledHtml = theTemplate(context);

  // Add the compiled html to the page
  $('.content-placeholder').html(theCompiledHtml);
});

 

3. Context

Handlebars builds on the best features of Mustache. And one these is the concept of context - the object where properties you include in curly braces are looked up. Every template you write has a context. On the top level, this is the JavaScript object that you pass to the compiled template. But helpers like #each or #with modify it, so that you can access the properties of the iterated object directly. The next example will make things clearer.

<!-- The #each helper iterates over an array of items. -->
<script id="example-template" type="text/x-handlebars-template">

  <!-- people is looked up on the global context, the one we pass to the compiled template -->

  {{#each people}}

    <!-- Here the context is each individual person. So we can access its properties directly: -->
    <p>{{firstName}} {{lastName}}</p>

  {{/each}}

</script>
$(function () {
  // Grab the template script
  var theTemplateScript = $("#example-template").html();

  // Compile the template
  var theTemplate = Handlebars.compile(theTemplateScript);

  // This is the default context, which is passed to the template
  var context = {
    people: [ 
      { firstName: 'Homer', lastName: 'Simpson' },
      { firstName: 'Peter', lastName: 'Griffin' },
      { firstName: 'Eric', lastName: 'Cartman' },
      { firstName: 'Kenny', lastName: 'McCormick' },
      { firstName: 'Bart', lastName: 'Simpson' }
    ]
  };

  // Pass our data to the template
  var theCompiledHtml = theTemplate(context);

  // Add the compiled html to the page
  $(document.body).append(theCompiledHtml);
});

 

4. Helpers

Handlebars doesn't allow you to write JavaScript directly within templates. Instead, it gives you helpers. These are JavaScript functions that you can call from your templates, and help you reuse code and create complex templates. To call a helper, just use it as an expression - {{helpername}}. You can pass parameters as well - {{helpername 12345}}, which are passed as parameters to your helper function.

To create a helper, use the registerHelper function. See the example below, which demonstrates a creating a helper, and a number of Handlebars' built-in ones:

<script id="built-in-helpers-template" type="text/x-handlebars-template">
  {{#each animals}}
    <p>
      The {{capitalize this.name}} says
      {{#if this.noise}}
        "{{this.noise}}".
      {{else}}
        nothing since its a {{this.name}}.
      {{/if}}
    </p>
  {{/each}}
</script>

<div class="content-placeholder"></div>
$(function () {

  // Register a helper
  Handlebars.registerHelper('capitalize', function(str){
    // str is the argument passed to the helper when called
    str = str || '';
    return str.slice(0,1).toUpperCase() + str.slice(1);
  });

  // Grab the template script
  var theTemplateScript = $("#built-in-helpers-template").html();

  // Compile the template
  var theTemplate = Handlebars.compile(theTemplateScript);

  // We will call this template on an array of objects
  var context = {
    animals:[
      {
        name: "cow",
        noise: "moooo"
      },
      {
        name: "cat",
        noise: "meow"
      },
      {
        name: "fish",
        noise: ""
      },
      {
        name: "farmer",
        noise: "Get off my property!"
      }
    ]
  };

  // Pass our data to the template
  var theCompiledHtml = theTemplate(context);

  // Add the compiled html to the page
  $('.content-placeholder').html(theCompiledHtml);

});

 

5. Block helpers

Block helpers are just like the regular ones, but they have an opening and a closing tag (like the #if and #each built-ins). These helpers can modify the HTML and content they are wrapped around. They are a bit more complicated to create, but are very powerful. You can use them to reuse functionality or to create large blocks of HTML in a reusable way (for example lists of items that you use on many places in your app).

To create a block helper, you again use Handlebars.registerHelper(). The difference is that this time we will use the second parameter of our callback function - options. It exposes a few useful properties that we will need. See the example below, which turns text uppercase.

<script id="block-expressions-template" type="text/x-handlebars-template">

  <p> The <b> {{#uppercase}} konami {{/uppercase}} </b> Code is a cheat code that appears in many video games.</p>

  <p>During the title screen before the game demo begins, the player could press the following sequence of buttons on the game controller to enable the cheat:</p>

  <p>{{#uppercase}}{{code}}{{/uppercase}}</p>

  <p>The code is also present as an Easter egg on a number of websites.</p>

</script>

<div class="content-placeholder"></div>
$(function () {
  // Grab the template script
  var theTemplateScript = $("#block-expressions-template").html();

  // This is our block helper
  // The name of our helper is provided as the first parameter - in this case 'uppercase'
  Handlebars.registerHelper('uppercase', function(options) {

    // "this" is the context that existed when calling the helper.

    // The options object has a special function - fn. This is a
    // compiled version of the template that is contained between the opening and closing
    // blocks of this helper. To get a string, call fn with the context:

    return options.fn(this).toUpperCase();

  });

  // Compile the template
  var theTemplate = Handlebars.compile(theTemplateScript);

  // Define our data object
  var context = {
    "code": "up up down down left right left right b a select start"
  };

  // Pass our data to the template
  var theCompiledHtml = theTemplate(context);

  // Add the compiled html to the page
  $('.content-placeholder').html(theCompiledHtml);

});

 

Resources and further reading

You now know enough to start using Handlebars in your web apps! But it never hurts to know a bit more, so here are a few more resources and articles if you wish to dig deeper in the library:

Share this article:

Comments