Buy Handlebars swag on DevSwag!

Handlebars provides the power necessary to let you build semantic templates effectively with no frustration.

Mustache templates are compatible with Handlebars, so you can take a Mustache template, import it into Handlebars, and start taking advantage of the extra Handlebars features.

Download: 1.3.0 Download: runtime-1.3.0

Getting Started

Handlebars templates look like regular HTML, with embedded handlebars expressions.
<div class="entry">
  <h1>{{title}}</h1>
  <div class="body">
    {{body}}
  </div>
</div>
A handlebars expression is a {{, some contents, followed by a }}
Learn More: Expressions
You can deliver a template to the browser by including it in a <script> tag.
<script id="entry-template" type="text/x-handlebars-template">
  template content
</script>
Compile a template in JavaScript by using Handlebars.compile
var source   = $("#entry-template").html();
var template = Handlebars.compile(source);
It is also possible to precompile your templates. This will result in a smaller required runtime library and significant savings from not having to compile the template in the browser. This can be especially important when working with mobile devices.
Learn More: Precompilation
Get the HTML result of evaluating a Handlebars template by executing the template with a context.
var context = {title: "My New Post", body: "This is my first post!"}
var html    = template(context);
results in
<div class="entry">
  <h1>My New Post</h1>
  <div class="body">
    This is my first post!
  </div>
</div>
Learn More: Execution

HTML Escaping

Handlebars HTML-escapes values returned by a {{expression}}. If you don't want Handlebars to escape a value, use the "triple-stash", {{{.
<div class="entry">
  <h1>{{title}}</h1>
  <div class="body">
    {{{body}}}
  </div>
</div>
with this context:
{
  title: "All about <p> Tags",
  body: "<p>This is a post about &lt;p&gt; tags</p>"
}
results in:
<div class="entry">
  <h1>All About &lt;p&gt; Tags</h1>
  <div class="body">
    <p>This is a post about &lt;p&gt; tags</p>
  </div>
</div>
Handlebars will not escape a Handlebars.SafeString. If you write a helper that generates its own HTML, you will usually want to return a new Handlebars.SafeString(result). In such a circumstance, you will want to manually escape parameters.
Handlebars.registerHelper('link', function(text, url) {
  text = Handlebars.Utils.escapeExpression(text);
  url  = Handlebars.Utils.escapeExpression(url);

  var result = '<a href="' + url + '">' + text + '</a>';

  return new Handlebars.SafeString(result);
});
This will escape the passed in parameters, but mark the response as safe, so Handlebars will not try to escape it even if the "triple-stash" is not used.

Block Expressions

Block expressions allow you to define helpers that will invoke a section of your template with a different context than the current. Let's consider a helper that will generate an HTML list:
{{#list people}}{{firstName}} {{lastName}}{{/list}}
If we have the following context:
{
  people: [
    {firstName: "Yehuda", lastName: "Katz"},
    {firstName: "Carl", lastName: "Lerche"},
    {firstName: "Alan", lastName: "Johnson"}
  ]
}
we would create a helper named list to generate our HTML list. The helper receives the people as its first parameter, and an options hash as its second parameter. The options hash contains a property named fn, which you can invoke with a context just as you would invoke a normal Handlebars template.
Handlebars.registerHelper('list', function(items, options) {
  var out = "<ul>";

  for(var i=0, l=items.length; i<l; i++) {
    out = out + "<li>" + options.fn(items[i]) + "</li>";
  }

  return out + "</ul>";
});
When executed, the template will render:
<ul>
  <li>Yehuda Katz</li>
  <li>Carl Lerche</li>
  <li>Alan Johnson</li>
</ul>
Block helpers have more features, such as the ability to create an else section (used, for instance, by the built-in if helper).
Since the contents of a block helper are escaped when you call options.fn(context), Handlebars does not escape the results of a block helper. If it did, inner content would be double-escaped!
Learn More: Block Helpers

Handlebars Paths

Handlebars supports simple paths, just like Mustache.
<p>{{name}}</p>
Handlebars also supports nested paths, making it possible to look up properties nested below the current context.
<div class="entry">
  <h1>{{title}}</h1>
  <h2>By {{author.name}}</h2>

  <div class="body">
    {{body}}
  </div>
</div>
That template works with this context
var context = {
  title: "My First Blog Post!",
  author: {
    id: 47,
    name: "Yehuda Katz"
  },
  body: "My first post. Wheeeee!"
};
This makes it possible to use Handlebars templates with more raw JSON objects.
Nested handlebars paths can also include ../ segments, which evaluate their paths against a parent context.
<h1>Comments</h1>

<div id="comments">
  {{#each comments}}
  <h2><a href="/posts/{{../permalink}}#{{id}}">{{title}}</a></h2>
  <div>{{body}}</div>
  {{/each}}
</div>
Even though the link is printed while in the context of a comment, it can still go back to the main context (the post) to retrieve its permalink.
The ../ path segment references the parent template scope, not one level up in the context. This is because block helpers can invoke a block with any context, so the notion of "one level up" isn't particularly meaningful except as a reference to the parent template scope.
Handlebars also allows for name conflict resolution between helpers and data fields via a this reference:
<p>{{./name}} or {{this/name}} or {{this.name}}</p>
Any of the above would cause the name field on the current context to be used rather than a helper of the same name.

Template comments with {{! }} or {{!-- --}}.

You can use comments in your handlebars code just as you would in your code. Since there is generally some level of logic, this is a good practice.
<div class="entry">
  {{! only output this author names if an author exists }}
  {{#if author}}
    <h1>{{firstName}} {{lastName}}</h1>
  {{/if}}
</div>
The comments will not be in the resulting output. If you'd like the comments to show up. Just use html comments, and they will be output.
<div class="entry">
  {{! This comment will not be in the output }}
  <!-- This comment will be in the output -->
</div>
Any comments that must contain }} or other handlebars tokens should use the {{!-- --}} syntax.

Helpers

Handlebars helpers can be accessed from any context in a template. You can register a helper with the Handlebars.registerHelper method.
<div class="post">
  <h1>By {{fullName author}}</h1>
  <div class="body">{{body}}</div>

  <h1>Comments</h1>

  {{#each comments}}
  <h2>By {{fullName author}}</h2>
  <div class="body">{{body}}</div>
  {{/each}}
</div>
when using this context and helpers:
var context = {
  author: {firstName: "Alan", lastName: "Johnson"},
  body: "I Love Handlebars",
  comments: [{
    author: {firstName: "Yehuda", lastName: "Katz"},
    body: "Me too!"
  }]
};

Handlebars.registerHelper('fullName', function(person) {
  return person.firstName + " " + person.lastName;
});
results in:
<div class="post">
  <h1>By Alan Johnson</h1>
  <div class="body">I Love Handlebars</div>

  <h1>Comments</h1>

  <h2>By Yehuda Katz</h2>
  <div class="body">Me Too!</div>
</div>
Helpers receive the current context as the this context of the function.
<ul>
  {{#each items}}
  <li>{{agree_button}}</li>
  {{/each}}
</ul>
when using this context and helpers:
var context = {
  items: [
    {name: "Handlebars", emotion: "love"},
    {name: "Mustache", emotion: "enjoy"},
    {name: "Ember", emotion: "want to learn"}
  ]
};

Handlebars.registerHelper('agree_button', function() {
  return new Handlebars.SafeString(
    "<button>I agree. I " + this.emotion + " " + this.name + "</button>"
  );
});
results in:
<ul>
  <li><button>I agree. I love Handlebars</button></li>
  <li><button>I agree. I enjoy Mustache</button></li>
  <li><button>I agree. I want to learn Ember</button></li>
</ul>
If your helper returns HTML that you do not want escaped, make sure to return a new Handlebars.SafeString.

Built-In Helpers

The with Block Helper

Normally, Handlebars templates are evaluated against the context passed into the compiled method.
var source   = "<p>{{lastName}}, {{firstName}}</p>";
var template = Handlebars.compile(source);
template({firstName: "Alan", lastName: "Johnson"});
results in
<p>Johnson, Alan</p>
You can shift the context for a section of a template by using the built-in with block helper.
<div class="entry">
  <h1>{{title}}</h1>

  {{#with author}}
  <h2>By {{firstName}} {{lastName}}</h2>
  {{/with}}
</div>
when used with this context:
{
  title: "My first post!",
  author: {
    firstName: "Charles",
    lastName: "Jolley"
  }
}
will result in:
<div class="entry">
  <h1>My first post!</h1>

  <h2>By Charles Jolley</h2>
</div>

The each block helper

You can iterate over a list using the built-in each helper. Inside the block, you can use this to reference the element being iterated over.
<ul class="people_list">
  {{#each people}}
  <li>{{this}}</li>
  {{/each}}
</ul>
when used with this context:
{
  people: [
    "Yehuda Katz",
    "Alan Johnson",
    "Charles Jolley"
  ]
}
will result in:
<ul class="people_list">
  <li>Yehuda Katz</li>
  <li>Alan Johnson</li>
  <li>Charles Jolley</li>
</ul>
You can use the this expression in any context to reference the current context.
You can optionally provide an {{else}} section which will display only when the list is empty.
{{#each paragraphs}}
  <p>{{this}}</p>
{{else}}
  <p class="empty">No content</p>
{{/each}}
When looping through items in each, you can optionally reference the current loop index via {{@index}}
{{#each array}}
  {{@index}}: {{this}}
{{/each}}
Additionally for object iteration, {{@key}} references the current key name:
{{#each object}}
  {{@key}}: {{this}}
{{/each}}
The first and last steps of iteration are noted via the @first and @last variables then iterating over an array. When iterating over an object only the @first is available.

The if block helper

You can use the if helper to conditionally render a block. If its argument returns false, undefined, null, "" or [] (a "falsy" value), Handlebars will not render the block.
<div class="entry">
  {{#if author}}
  <h1>{{firstName}} {{lastName}}</h1>
  {{/if}}
</div>
when used with an empty ({}) context, author will be undefined, resulting in:
<div class="entry">
</div>
When using a block expression, you can specify a template section to run if the expression returns a falsy value. The section, marked by {{else}} is called an "else section".
<div class="entry">
  {{#if author}}
    <h1>{{firstName}} {{lastName}}</h1>
  {{else}}
    <h1>Unknown Author</h1>
  {{/if}}
</div>

The unless block helper

You can use the unless helper as the inverse of the if helper. Its block will be rendered if the expression returns a falsy value.
<div class="entry">
  {{#unless license}}
  <h3 class="warning">WARNING: This entry does not have a license!</h3>
  {{/unless}}
</div>
If looking up license under the current context returns a falsy value, Handlebars will render the warning. Otherwise, it will render nothing.

The log block helper

The log helper allows for logging of context state while executing a template.
{{log "Look at me!"}}
Delegates to Handlebars.logger.log which may be overriden to perform custom logging.

Built-In Utilities

Handlebars offers a varity of utility methods for helpers. These are available on the Handlebars.Util namespace.
Learn More: Utilities
Fork me on GitHub