Learn Handlebars in 10 Minutes or Less

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:

  • Handlebars.js - Handlebars' home is full of great documentation and examples.
  • Try Handlebars.js - try out different Handlebars scenarios in your browser (it is for an older version of handlebars, unfortunately, but the basics are pretty much the same).
  • Handlebars Helpers - a collection of 130+ handlebars helpers in ~20 categories.
  • SWAG - more handlebars helpers.
  • Handlebars API Reference.
Bootstrap Studio

The revolutionary web design tool for creating responsive websites and apps.

Learn more

Related Articles

Martin Angelov

Handlebars is the templating engine for Ember.js, which may explain why it is so popular. It improves on Mustache, but it's improvements are JavaScript specific, so Handlebars doesn't work in non-js environments. On the other hand, Mustache is implemented in lots of languages. So if you ever need to choose between these two, keep these differences in mind.

Also, the support for native HTML templates is very good, but I still think that Handlebars is pretty much the best client-side templating engine at the moment.

Great into, but where are you getting the data from?
Where do you connect to the DB/Data Source? Is that done with handlebars?

Danny Markov

Nope, no external services. Click the "JS" tabs of the editors, the data is passed as a plain JS object after the templates are compiled. But of course you can just pass data that has been fetched externally.

Ah OK,
Is there any chance there might be a tutorial on connecting the dots?
Like getting data from a DB? Or PHP etc..?
Cheers

+1 Great job

Georgi Yanev

Not bad at all. Found it very useful. Cheers!

Great job, easy and quick guide

Thank you!
This is a great introduction to Handelbars.

Thank you , this is a great introduction .

2017 and still found this very useful, but I'd suggest you write something like 'click the js tab to see the js' or something, I just had not seen the js tab, and made me loose like half an hour

Luciano Oliveira

Thanks Danny for another great tutorial.