Handlebars - Builtin Helpers

handlebars

What is the purpose of the if helper?

You can use the if helper to conditionally render a block. If its argument returns false, undefined, null, "", 0, or [], Handlebars will not render the block.

{{#if isActive}}
  <img src="star.gif" alt="Active">
{{else}}
  <img src="cry.gif" alt="Inactive">
{{/if}}

Control structures typically do not change the current context, instead they decide whether or not to invoke the block based upon some variable.

When writing a conditional, you will often want to make it possible for templates to provide a block of HTML that your helper should insert if the conditional evaluates to false. Handlebars handles this problem by providing generic else functionality to block helpers (see the above example)

As with the iterators, Handlebars' built-in if and unless control structures are implemented as regular Handlebars helpers:

Handlebars.registerHelper('if', function(conditional, options) {
  if(conditional) {
    return options.fn(this);
  } else {
    return options.inverse(this);
  }
});

Handlebars provides the block for the else fragment as options.inverse. You do not need to check for the existence of the else fragment: Handlebars will detect it automatically and register a "noop" function (if the {{else}} construct is not present in the template, options.inverse is automatically configured as a noop function.

Handlebars provides additional metadata to block helpers by attaching them as properties of the options hash.

Conditionals may also be chained by including the subsequent helper call within the else mustache.

{{#if isActive}}
  <img src="star.gif" alt="Active">
{{else if isInactive}}
  <img src="cry.gif" alt="Inactive">
{{/if}}

It is not necessary to use the same helper in subsequent calls, the unless helper could be used in the else portion as with any other helper. When the helper values are different, the closing mustache should match the opening helper name.

What is the purpose of the unless 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.

What is the purpose of the each helper?

<div class="comments">
  {{#each comments}}
    <div class="comment">
      <h2>{{subject}}</h2>
      {{{body}}}
    </div>
  {{/each}}
</div>

In this case, we want to invoke the block passed to each once for each element in the comments array. The each built-in helper is also registered like other helpers:

Handlebars.registerHelper('each', function(context, options) {
  var ret = "";

  for(var i=0, j=context.length; i<j; i++) {
    ret = ret + options.fn(context[i]);
  }

  return ret;
});

In this case, we iterate over the items in the passed parameter, invoking the block once with each item. As we iterate, we build up a string result, and then return it.

The each helper can be used to iterate over an array or an object. The syntax of the helper is {{#each ArrayOrObjectName}} 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.

Template:
{{#each countries}}
  {{@index}} : {{this}}<br>
{{/each}}

{{#each names}}
  Name : {{firstName}} {{lastName}}<br>
{{/each}}

Context:
var context = {
  "countries":["Russia","India","USA"],
  "names" : [
    {"firstName":"Ritesh","lastName":"Kumar"},
    {"firstName":"John","lastName":"Doe"}
  ]
}

Output:
0 : Russia
1 : India
2 : USA
Name : Ritesh Kumar
Name : John Doe

In Handlebars, each is one of the built-in helpers; it allows you to iterate through objects and arrays. Inside the block, we can use @key for the former (objects), and @index for the later (arrays). In addition, each item is referred to as this. When an item is an object itself, this can be omitted and just the property name is used to reference the value of that property. http://webapplog.com/handlebars/

Template:
<div>
{{#each languages}}
  <p>{{@index}}. {{this}}</p>
{{/each}}
</div>

Data:
{languages: ['php', 'node', 'ruby']}

Output:
<div>
  <p>0. php</p>
  <p>1. node</p>
  <p>2. ruby</p>
</div>

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.

Template:
<ul class="people_list">
  {{#each people}}
    <li>{{this}}</li>
  {{/each}}
</ul>

Context:
{
  people: [
    "Yehuda Katz",
    "Alan Johnson",
    "Charles Jolley"
  ]
}

Output:
<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}}

When iterating through an object, we can optionally reference the current property name via {{@key}}:

{{#each object}}
  {{@key}}: {{this}}
{{/each}}

The first and last steps of iteration are noted via the @first and @last variables when iterating over an array. When iterating over an object only the @first is available.

Nested each blocks may access the interation variables via depth based paths. To access the parent index, for example, {{@../index}} can be used.

The each helper also supports block parameters, allowing for named references anywhere in the block.

{{#each array as |value, key|}}
  {{#each child as |childValue, childKey|}}
    {{key}} - {{childKey}}. {{childValue}}
  {{/each}}
{{/each}}

Will create a key and value variable that children may access without the need for depthed variable references. In the example above, {{key}} is identical to {{@../key}} but in many cases is more readable.

What is the purpose of the 'with' helper?

The with helper demonstrates how to pass a parameter to your helper. When a helper is called with a parameter, it is invoked with whatever context the template passed in.

<div class="entry">
  <h1>{{title}}</h1>
  {{#with story}}
    <div class="intro">{{{intro}}}</div>
    <div class="body">{{{body}}}</div>
  {{/with}}
</div>

You might find a helper like this useful if a section of your JSON object contains deeply nested properties, and you want to avoid repeating the parent name. The above template could be useful with a JSON like:

{
  title: "First Post",
  story: {
    intro: "Before the jump",
    body: "After the jump"
  }
}

Implementing a helper like this is a lot like implementing the noop helper. Helpers can take parameters, and parameters are evaluated just like expressions used directly inside mustache blocks.

Handlebars.registerHelper('with', function(context, options) {
  return options.fn(context);
});

Parameters are passed to helpers in the order that they are passed, followed by the options hash.

The options.fn function runs the section of template inside the block with whatever context you give it. http://code.tutsplus.com/tutorials/an-introduction-to-handlebars--net-27761

In case there’s an object with nested properties, and there are a lot of them, it’s possible to use with to pass the context.

Template:
{{#with user}}
<p>{{name}}</p>
{{#with contact}}
<span>Twitter: @{{twitter}}</span>
{{/with}}
<span>Address: {{address.city}},
{{/with}}
{{user.address.state}}</span>

Data:
{user: {
  contact: {
    email: 'hi@azat.co',
    twitter: 'azat_co'
  },
  address: {
    city: 'San Francisco',
    state: 'California'
  },
  name: 'Azat'
}}

<p>Azat</p>
<span>Twitter: @azat_co</span>
<span>Address: San Francisco, California
</span>

So, instead of use user.contact.email and user.contact.twitter (if we have a lot of properties), we can use the with helper as demonstrated in the above example to reduce the amount of typing that we have to do.

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"});

Output:
<p>Johnson, Alan</p>

You can shift the context for a section of a template by using the built-in with block helper.

Template:
<div class="entry">
  <h1>{{title}}</h1>

  {{#with author}}
  <h2>By {{firstName}} {{lastName}}</h2>
  {{/with}}
</div>

Context:
{
  title: "My first post!",
  author: {
    firstName: "Charles",
    lastName: "Jolley"
  }
}

Output:
<div class="entry">
  <h1>My first post!</h1>

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

with can also be used with block parameters to define known references in the current block. The example above can be converted to

<div class="entry">
  <h1>{{title}}</h1>

  {{#with author as |myAuthor|}}
  <h2>By {{myAuthor.firstName}} {{myAuthor.lastName}}</h2>
  {{/with}}
</div>

Which allows for complex templates to potentially provide clearer code than ../ depthed references allow for.

You can optionally provide an else section which will display only when the passed value is empty.

{{#with author}}
  <p>{{name}}</p>
{{else}}
  <p class="empty">No content</p>
{{/with}}

What is the purpose of the lookup helper?

The lookup helper allows for dynamic parameter resolution using Handlebars variables. This is useful for resolving values for array indexes.

{{#each bar}}
  {{lookup ../foo @index}}
{{/each}}

What is the purpose of 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.

Any number of arguments may be passed to this method and all will be forwarded to the logger.

{{log "This is logged" foo "And so is this"}}

The log level may be set using the level hash parameter. Supported values are debug, info, warn, and error. When omitted, info is the default value:

{{log "Log!" level="error"}}

Logging is conditional based on the level and to value set in Handlebars.logger.level, which defaults to info. All log statements at or above the current level will be output.

What is the purpose of the blockHelperMissing helper?

Implicitly called when a helper can not be directly resolved in the environment's helpers hash.

{{#foo}}{{/foo}}

will call this helper with the resolved value of foo on the current context and the options.name field set to "foo". For instances where there is no registered helper named foo. his may be overriden by users that wish to change the behavior of block evaluation. For example

Handlebars.registerHelper('blockHelperMissing', function(context, options) {
  throw new Handlebars.Exception('Only if or each is allowed');
});

could be used to prevent the use of mustache-style block evaluation in favor of the more efficent if and each helpers.

What is the purpose of the helperMissing helper?

Internal helper that is called when a potential helper expression was not found in either the environment helpers or the current context. For cases where both are run, this is run prior to the blockHelperMissing helper.

{{foo}}
{{foo bar}}
{{#foo}}{{/foo}}

Will each call this helper, passing any arguments that would have been otherwise passed to a helper of the same name. This helper is not called when using knownHelpersOnly mode.

This may be overriden by applications. To force the existence of the field, the following may be used:

Handlebars.registerHelper('helperMissing', function(/* [args, ] options */) {
  var options = arguments[arguments.length - 1];
  throw new Handlebars.Exception('Unknown field: ' + options.name);
});

What is the purpose of the raw-helper helper?

Raw blocks are available for templates needing to handle unprocessed mustache blocks.

{{{{raw-helper}}}}
  {{bar}}
{{{{/raw-helper}}}}

will execute the helper raw-helper without interpretting the content.

Handlebars.registerHelper('raw-helper', function(options) {
  return options.fn();
});

will render:

{{bar}}

What is the purpose of the debug helper?

Handlebars.registerHelper("debug", function(optionalValue) {
  console.log("Current Context");
  console.log("====================");
  console.log(this);

  if (optionalValue) {
    console.log("Value");
    console.log("====================");
    console.log(optionalValue);
  }
});

You could then use that helper in any template like:

{{debug someValue}}

and you’ll see output in the JavaScript console letting you know what’s going on:

Current Context
====================
email: "alan@test.com"
first_name: "Alan"
last_name: "Johnson"
member_since: "Mar 25, 2011"
phone: "1234567890"
stripeClass: "even"
__proto__: Object
Value
====================
Alan
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License