How to use Handlebars.js for templating

Handlebars Templating Library: an easy-to-use introductory guide

© handlebarsjs

Sometimes, we need to display the same basic HTML, but with some customized data interspersed here and there. The Handlebars.js library is perfect for this. It takes less than 5 minutes to learn how to use this simple and efficient templating tool.

Here are the 7 basic steps.


Steps

  • In your HTML file…
  1. Include the handlebars.js library file in your <head> tag
  2. Include your own custom js file just before the closing </body> tag
  3. Create the template HTML inside <script type="text/x-handlebars"></script> tags
  • In your custom JS file…
  1. Capture the template HTML as a string
  2. Create a function to generate template instances using Handlebars.compile() and the string from the previous step
  3. Create an instance of the template using the function and an object literal
  4. Incorporate the template instance into a DOM element

In HTML File

1. Include the handlebars.js library file

<head>
  <script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>
</head>

2. Include your own custom .js file

<body>
  ... some stuff

  <div id="template1area"></div>

  ... some stuff

  <script src="myHandlebars.js"></script>
</body>

Alternatively, instead of including the custom file just before your closing </body> tag, you can also include it right after the handlebars.js library in the <head> tag above, but just make sure you nest your code inside an event listener that fires after the DOM is fully loaded.

It’s important that your custom .js file loads after both the handlebars.js library and the DOM, since we’ll need to reference and add to existing DOM elements.

Note: the template1area <div> will only be relevant and needed for the last step: step 7.

3. Create the template HTML

<script id="template1" type="text/x-handlebars">
  <h2>{{name}}</h2>

  {{#if category}}
    <strong>Category: </strong> {{category}}<br>
  {{/if}}

  <strong>Link: </strong>
  {{#if link}}
    <a href ="{{link}}">{{link}}</a>
  {{else}}
    none
  {{/if}}

  <p>
  {{#if miscellaneous}}
    {{{miscellaneous}}}
  {{/if}}
  </p>
</script>

Several things to point out here:

  1. The main functional advantage of wrapping the template HTML inside of this specific type of <script> tag is that we do not display the contents of the template HTML, nor try to run it as JavaScript. We could have instead wrapped it inside a <div> and made sure the display was set to none, but that may cause some unintended consequences later and is considered bad practice. The point is just that there is nothing particularly special about this wrapper, and we care more about what’s inside of it. But using the specific type of <script> tag, as we’ve done here, more explicitly lets other developers know what the content of the wrapper is supposed to be used for.
  2. Notice that we use two different types of curly braces that will contain customizable data: double curlies {{ something }}, and tripple curlies {{{ somethingElse }}}. The former will render something as text, and the latter will parse somethingElse as HTML content.
  3. We can place the code above anywhere inside our <body> tags, but not after.
  4. Note that we can use conditional logic inside the template with #if.

In custom JS File (e.g. myHandlebars.js)

4. Capture the template HTML as a string

let template1 = document.querySelector("#template1").innerHTML;

Note: Although we could directly create our template1 string right here instead of defining the HTML template in our HTML file (step 3) and having to capture it here, this approach is better because it better adheres to the separation of concerns principle.

Namely: most of your HTML should be in your HTML file, most of your styling in your CSS file, and most of your logic and behavior in your JS file.

5. Create a function using Handlebars.compile()

let template1Func = Handlebars.compile(template1);

This is essentially the kernel of magic that the the Handlebars library provides. Call Handlebars.compile() with a string that contains a template that resembles step 3 (i.e. with the curly braces that look like handlebar mustaches), and it will return a smart function you can use to create any instance/customized version of the template you want.

We’ll see an example of that next.

6. Create an instance of the template

let temp1obj1 = {
  name: "Vahid's Blog",
  category: "Technical blog",
  link: "https://vahid.blog",
  miscellaneous:
    "This part here can incorporate HTML tags
    like <strong>strong</strong> and <em>em</em>
    because the template displays it using triple curlies.",
};

let temp1FromObj1 = template1Func(temp1obj1);

The object containing our customized data (that we use as an argument passed to the template function) can be either a JS object literal, like temp1obj1 above, or a JSON object.

The function returns a string containing the customized HTML from the template1 template filled in with the temp1obj1 data, representing an instance of the template. This string is captured by the temp1FromObj1 variable.

7. Incorporate the template instance

document.querySelector("#template1area").innerHTML = temp1FromObj1;

Of course, you can incorporate the instance into any element you want, including the document.body itself, or a new element entirely. Just make sure to attach it to the DOM.

And that’s it! There’s a lot more you can do within Handlebars templates, including iterators, partials, and targeting nested objects and their properties. Check out the docs for more info.

Special thanks to Alex Strick, whose post was helpful in getting me started on Handlebars.

Vahid Dejwakh
Vahid Dejwakh
Software Engineer at Microsoft;
Co-Creator of the Fjord Framework

Vahid writes about interesting ideas at the intersection of software, system design, data, philosophy, psychology, policy, and business. He enjoys coffee and has a palate for spicy and diverse foods.

comments powered by Disqus

Related