Nowadays the majority of the Web consists of dynamic applications in which the data keep changing frequently. As a result, there is a continuous need to update the data rendered on the browser. This is where JavaScript templating engines come to the rescue and become so useful. They simplify the process of manually updating the view and at the same time they improve the structure of the application by allowing developers to separate the business logic from the rest of the code. Some of the most well-known JavaScript templating engines are Mustache, Underscore, EJS, and Handlebars. In this article we’ll focus our attention on Handlebars by discussing its main features.
Handlebars is a logic-less templating engine that dynamically generates your HTML page. It’s an extension of Mustache with a few additional features. Mustache is fully logic-less but Handlebars adds minimal logic thanks to the use of some helpers (such as if, with, unless, each and more) that we’ll discuss further in this article. As a matter of fact, we can say that Handlebars is a superset of Mustache.
Handlebars can be loaded into the browser just like any other JavaScript file:
<span><span><span><script</span> src<span>="/path/to/handlebars.min.js"</span>></span><span><span></script</span>></span></span>
If you’re asking why you should employ this templating engine rather than another one, you should take a look at its pros. Here is a short list:
I hope that this short recap helps you in deciding if it’s worth using Handlebars or not.
As shown in the above diagram, the way Handlebars works can be summarised as follows:
To understand the above process, let’s start with a demo that explains in detail all the above mentioned steps.
Templates can be written both in the HTML file or separately. In the first case, they appear inside the <script> tag with a type="text/x-handlebars-template" attribute and an ID. The variables are written in double curly braces {{}} and are known as expressions. Here is an example:</script>
<span><span><span><script</span> src<span>="/path/to/handlebars.min.js"</span>></span><span><span></script</span>></span></span>
With this markup in place, we can see what we have to do use it. In your JavaScript file we firstly need to retrieve the template from the HTML document. In the following example, we’ll use the ID of the template for this purpose. After the template has been retrieved, we can compile it by using the Handlebars.compile() method which returns a function. This function is then executed by passing the context as an argument. When the execution is complete, the function returns the desired HTML with all the variables replaced by their corresponding values. At this point we can inject the HTML into our web page.
Turning this description into code results in the following snippet:
<span><span><span><script</span> id<span>="handlebars-demo"</span> type<span>="text/x-handlebars-template"</span>></span><span><span><div>My name is {{name}}. I am a {{occupation}}.</div></span></span><span><span></script</span>></span></span>
A live demo of this code can be found in this Codepen demo
Now it’s time to dive a bit deeper into Handlebars. We’ll go through a few important terms and syntaxes that form the core of Handlebars.
We already saw expressions in the above section. The variables used inside the templates are surrounded by double curly braces {{}} and are known as expressions:
<span>// Retrieve the template data from the HTML (jQuery is used here).var template = $('#handlebars-demo').html(); </span><span>// Compile the template data into a functionvar templateScript = Handlebars.compile(template); </span><span>var context = { "name" : "Ritesh Kumar", "occupation" : "developer" }; </span><span>// html = 'My name is Ritesh Kumar. I am a developer.'var html = templateScript(context); </span><span>// Insert the HTML code into the page$(document.body).append(html);</span>
Handlebars can escape the value returned by the expression. For example the character
<span>My name is {{name}}</span>
is used with the context variable reported below:
I am learning {{language}}. It is {{{adjective}}}.
the resulting HTML will be:
<span>var context = {"language" : "<h3>Handlebars</h3>","adjective": "<h3>awesome</h3>"}</span>
A live demo that shows this feature can be found in this Codepen demo
We can also write comments inside Handlebars templates. The syntax for Handlebars comments is {{!TypeYourCommentHere}}. However, every comment that has }} in it or any other symbol that has a special meaning in Handlebars should be written in the form {{!--TypeYourCommentHere--}}. Handlebars comments are not visible in the HTML but if you want to show them, you can use the standard HTML comment: .
If we apply all these concepts to the template we’re using, we can come up with the code shown below:
<span><span><span><script</span> src<span>="/path/to/handlebars.min.js"</span>></span><span><span></script</span>></span></span>
If we use the previous template with the context variable reported below:
<span><span><span><script</span> id<span>="handlebars-demo"</span> type<span>="text/x-handlebars-template"</span>></span><span><span><div>My name is {{name}}. I am a {{occupation}}.</div></span></span><span><span></script</span>></span></span>
the HTML output will be:
<span>// Retrieve the template data from the HTML (jQuery is used here).var template = $('#handlebars-demo').html(); </span><span>// Compile the template data into a functionvar templateScript = Handlebars.compile(template); </span><span>var context = { "name" : "Ritesh Kumar", "occupation" : "developer" }; </span><span>// html = 'My name is Ritesh Kumar. I am a developer.'var html = templateScript(context); </span><span>// Insert the HTML code into the page$(document.body).append(html);</span>
which will result in the browser not showing the content inside the standard HTML comment. A demo of this example can be found here.
In Handlebars, blocks are expressions that have a block opening ({{# }}) and closing ({{/}}). We’ll study in depth this topic later while focusing on helpers. For now, take a look at how an if block is written:
<span>My name is {{name}}</span>
Handlebars supports both normal and nested path, making it possible to look up properties nested below the current context. Handlebars also supports the ../ path segment. This segment references to the parent template scope and not to one level up in the context.
For better understanding this topic, we’ll employ the example below in which we use the each helper (discussed in details later on). As you might expect, the latter iterates over the items of an array.
In this example, we’ll use the following template:
I am learning {{language}}. It is {{{adjective}}}.
By providing this context variable:
<span>var context = {"language" : "<h3>Handlebars</h3>","adjective": "<h3>awesome</h3>"}</span>
we’ll obtain the output showed below:
I am learning <span><span><span><h3</span>></span>Handlebars<span><span></h3</span>></span>. It is <span><span><h3</span>></span>awesome<span><span></h3</span>></span></span>
Like the other small snippets we’ve created so far, this example is available on Codepen
Even though Handlebars is a logic-less templating engine, it can execute simple logics using helpers. A Handlebars helper is a simple identifier that may be followed by parameters (separated by a space), as shown below:
<span><!-- I am learning {{language}} -->I am learning {{language}}. It is {{!--adjective--}}</span>
Each parameter is a Handlebars expression. These helpers can be accessed from any context in a template.
The terms “block”, “helper”, and “block helper” are sometimes used interchangeably as most of the built-in helpers are blocks, although there are function helpers that are a bit different from block helpers. We’ll discuss them while covering custom helpers.
Some built-in helpers are if, each, unless, and with. Let’s learn more.
The each helper is used to iterate over an array. The syntax of the helper is {{#each ArrayName}} YourContent {{/each}} . We can refer to the individual array items by using the keyword this inside the block. The index of the array’s element can be rendered by using {{@index}}. The example below illustrates the use of the each helper.
If we employ the following template:
<span><span><span><script</span> src<span>="/path/to/handlebars.min.js"</span>></span><span><span></script</span>></span></span>
in conjunction with this context variable:
<span><span><span><script</span> id<span>="handlebars-demo"</span> type<span>="text/x-handlebars-template"</span>></span><span><span><div>My name is {{name}}. I am a {{occupation}}.</div></span></span><span><span></script</span>></span></span>
then the output will be:
<span>// Retrieve the template data from the HTML (jQuery is used here).var template = $('#handlebars-demo').html(); </span><span>// Compile the template data into a functionvar templateScript = Handlebars.compile(template); </span><span>var context = { "name" : "Ritesh Kumar", "occupation" : "developer" }; </span><span>// html = 'My name is Ritesh Kumar. I am a developer.'var html = templateScript(context); </span><span>// Insert the HTML code into the page$(document.body).append(html);</span>
A live demo of this example can be found on Codepen.
The if helper is similar to an if statement. If the condition evaluates to a truthy value, Handlebars will render the block. We can also specify a template section known as “else section”, by using {{else}}. The unless helper is the inverse of the if helper. It renders the block when the condition evaluates to a falsy value.
To show how the if helper works, let’s consider the template below:
<span>My name is {{name}}</span>
If we provide the following context variable:
I am learning {{language}}. It is {{{adjective}}}.
We’ll obtain the result reported below:
<span>var context = {"language" : "<h3>Handlebars</h3>","adjective": "<h3>awesome</h3>"}</span>
This happens because an empty array is a falsy value.
In case you want to play with helpers, you can take a look at the live demo I created on Codepen.
You can create your own helpers to perform complex logics using the expression system that Handlebars provides. There are two kinds of helpers: function helpers and block helpers. The first definition is meant for a single expression, while the latter is used for block expressions. The arguments provided to the callback function are the parameters written after the helper’s name, separated by a space. The helpers are created using Handlebars.registerHelper() method:
I am learning <span><span><span><h3</span>></span>Handlebars<span><span></h3</span>></span>. It is <span><span><h3</span>></span>awesome<span><span></h3</span>></span></span>
The syntax for a function helper is {{helperName parameter1 parameter2 ...}}. To better understand how to proceed with the implementation, let’s create a function helper called studyStatus which returns a string that will be “passed” if passingYear = 2015:
<span><!-- I am learning {{language}} -->I am learning {{language}}. It is {{!--adjective--}}</span>
In our example the parameter is only one. However, if we want to pass more parameters to the helper’s callback function we can write them in the template after the first parameter separated by a space.
Let’s develop an example with this template:
<span>var context = {"language" : "Handlebars","adjective": "awesome"}</span>
and with the following context variable:
<span><!-- I am learning Handlebars -->I am learning Handlebars. It is</span>
In this case, the output will be:
{{#if boolean}}Some Content here{{/if}}
A live demo of this example is available here.
Custom block helpers are used in the same way as function helpers, but the syntax is a bit different. The syntax of block helpers is:
<span><span><span><script</span> src<span>="/path/to/handlebars.min.js"</span>></span><span><span></script</span>></span></span>
When we register a custom block helper, Handlebars automatically adds an options object as the last parameter to the callback function. This options object has a fn() method that allows us to change the context of the object temporarily to access a certain property. Let’s change the example of the previous section by using a block helper named studyStatus but with the same context variable:
<span><span><span><script</span> id<span>="handlebars-demo"</span> type<span>="text/x-handlebars-template"</span>></span><span><span><div>My name is {{name}}. I am a {{occupation}}.</div></span></span><span><span></script</span>></span></span>
If this code is used in conjunction with the template defined below
<span>// Retrieve the template data from the HTML (jQuery is used here).var template = $('#handlebars-demo').html(); </span><span>// Compile the template data into a functionvar templateScript = Handlebars.compile(template); </span><span>var context = { "name" : "Ritesh Kumar", "occupation" : "developer" }; </span><span>// html = 'My name is Ritesh Kumar. I am a developer.'var html = templateScript(context); </span><span>// Insert the HTML code into the page$(document.body).append(html);</span>
we’ll obtain the following result:
<span>My name is {{name}}</span>
And here is the Codepen demo.
Handlebars partials are templates that can be shared among different templates. They are written as {{> partialName}}. Before using them in the HTML, we need to register the partial using Handlebars.registerPartial() method. The following example will help you in understanding how to register a partial named partialTemplate:
I am learning {{language}}. It is {{{adjective}}}.
When used with the template defined below
<span>var context = {"language" : "<h3>Handlebars</h3>","adjective": "<h3>awesome</h3>"}</span>
It’ll give the following result:
I am learning <span><span><span><h3</span>></span>Handlebars<span><span></h3</span>></span>. It is <span><span><h3</span>></span>awesome<span><span></h3</span>></span></span>
A live demo of this code can be found in this Codepen demo.
As we have seen, the first thing Handlebars does is to compile the template into a function. This is one of the most expensive operations to perform on the client. We can improve the performance of the application if we precompile templateScript and then send the compiled version to the client. In that case, the only task needed to be performed on the client will be the execution of that function. Since the precompiled file is a script, we can load the script in HTML as a normal file. Let’s see how all this stuff can be done.
Firstly, you have to install Handlebars globally by using npm install handlebars -g. Please, be sure that different templates are written in separate files with different file names and with the .handlebars extensions (for example demo.handlebars). There is no need of using the <script> tag inside those files.</script>
<span><!-- I am learning {{language}} -->I am learning {{language}}. It is {{!--adjective--}}</span>
Now store all the template files in a single folder named templates. You can use any folder name you wish but if you do that, please don’t forget to change the following command accordingly. So, open the terminal and execute the command:
<span>var context = {"language" : "Handlebars","adjective": "awesome"}</span>
This command will generate a file named templatesCompiled.js that contains all the compiled templates. The compiler will insert the templates in Handlebars.templates. If the input file is demo.handlebars, then it will be inserted at Handlebars.templates.demo
Now we have to include templatesCompiled.js in the HTML file as a normal script. It’s important to note that we don’t need to load the whole Handlebars library as the compiler itself is not needed anymore. We can use the smaller “runtime” build instead:
<span><span><span><script</span> src<span>="/path/to/handlebars.min.js"</span>></span><span><span></script</span>></span></span>
Now we can employ the template that was originally present in demo.handlebars by using the following code:
<span><span><span><script</span> id<span>="handlebars-demo"</span> type<span>="text/x-handlebars-template"</span>></span><span><span><div>My name is {{name}}. I am a {{occupation}}.</div></span></span><span><span></script</span>></span></span>
The final output will be the following:
<span>// Retrieve the template data from the HTML (jQuery is used here).var template = $('#handlebars-demo').html(); </span><span>// Compile the template data into a functionvar templateScript = Handlebars.compile(template); </span><span>var context = { "name" : "Ritesh Kumar", "occupation" : "developer" }; </span><span>// html = 'My name is Ritesh Kumar. I am a developer.'var html = templateScript(context); </span><span>// Insert the HTML code into the page$(document.body).append(html);</span>
This method will significantly increase the performance of the application and the page loading time also decreases as we are using the runtime build of Handlebars that is lighter than the whole library.
The code of this whole precompilation demo is available on GitHub.
In this article we have discussed the basic concepts of Handlebars. We also examined its frequently used functions and syntaxes. I hope you enjoyed this tutorial and you’ll use the demos included to have a good grasp of this topic. I’ll look forward to reading your comments.
In case you don’t want to download the library but you still want to try it, you can play with Handlebars online at http://tryhandlebarsjs.com/.
Handlebars.js is a JavaScript templating library used in web development to create dynamic web pages and generate HTML content based on data. It enables the creation of reusable templates with placeholders (handlebars) for data insertion. This library facilitates two-way data binding, allowing templates to automatically update when data changes. Developers commonly use Handlebars.js for client-side rendering, conditional logic, and data iteration. It promotes separation of concerns between HTML structure and data, making it a valuable tool for building interactive and data-driven web applications while enhancing code maintainability and security.
Handlebars is typically used in conjunction with HTML, rather than as a replacement. It offers several advantages when combined with HTML, including dynamic data binding, code reusability, a clear separation of concerns between presentation and data, client-side rendering, consistency in content generation, enhanced security through code separation, and support for localization. These benefits collectively make Handlebars a valuable tool for building dynamic and maintainable web applications while still relying on HTML for defining the basic structure of web pages.
At the time of writing, Handlebars is not deprecated, and it remains a viable and widely used JavaScript templating library in web development.
A Handlebars template is a text-based structure that defines the layout and structure of dynamic HTML content in web development. Handlebars is a JavaScript templating library that allows you to create these templates, making it easier to generate HTML content based on data.
In a Handlebars template, you can include placeholders, known as “handlebars,” that represent dynamic data. These handlebars are enclosed in double curly braces {{ }}. For example:
Hello, {{ name }}!
Hello, John!
The choice between Handlebars and Mustache depends on your project’s requirements and priorities. Handlebars offers more advanced features, making it suitable for complex templating needs and projects where a larger ecosystem and community support are important. Mustache, on the other hand, is simpler and follows a “logic-less” philosophy, making it a good choice for projects that prioritize simplicity and portability across multiple programming languages.
The above is the detailed content of A Beginner's Guide to Handlebars. For more information, please follow other related articles on the PHP Chinese website!