Handlebars - Helper - Advance

handlebars

How can a block helper inject private variables into their child templates?

Block helpers can also inject private variables into their child templates. This can be useful to add extra information that is not in the original context data. For example, when iterating over a list, you may provide the current index as a private variable.

{{#list array}}
  {{@index}}. {{title}}
{{/list}}

Handlebars.registerHelper('list', function(context, options) {
  var out = "<ul>", data;

  if (options.data) {
    data = Handlebars.createFrame(options.data);
  }

  for (var i=0; i<context.length; i++) {
    if (data) {
      data.index = i;
    }

    out += "<li>" + options.fn(context[i], { data: data }) + "</li>";
  }

  out += "</ul>";
  return out;
});

Private variables provided via the data option are available in all descendent scopes. Private variables defined in parent scopes may be accessed via pathed queries. To access the index field of the parent iterator, @../index may be used.

Make sure you create a new data frame in each helper that assigns its own data. Otherwise, downstream helpers might unexpectedly mutate upstream variables.

Also ensure that the data field is defined prior to attempting to interact with an existing data object. The private variable behavior is condtionally compiled and some templates might not create this field.

How can we receive named parameters from supporting helpers?

New in Handlebars 3.0, it's possible to receive named parameters from supporting helpers.

{{#each users as |user userId|}}
  Id: {{userId}} Name: {{user.name}}
{{/each}}

In this particular example, user will have the same value as the current context and userId will have the index value for the iteration. This allows for nested helpers to avoid name conflicts that can occur with private variables.

{{#each users as |user userId|}}
  {{#each user.book as |book bookId|}}
    User Id: {{userId}} Book Id: {{bookId}}
  {{/each}}
{{/each}}

A number of builtin helpers support block parameters and any custom helper may provide them through the blockParams options field.

Handlebars.registerHelper('block-params', function() {
  var args = [],
      options = arguments[arguments.length - 1];
  for (var i = 0; i < arguments.length - 1; i++) {
    args.push(arguments[i]);
  }

  return options.fn(this, {data: options.data, blockParams: args});
});

{{#block-params 1 2 3 as |foo bar baz|}}
  {{foo}} {{bar}} {{baz}}
{{/block-params}}

Implements a helper that allows for named variable declarations within a given block. This example would output 1 2 3 on render.

Helpers can determine the number of block paramemters referenced by the template via the options.fn.blockParams field, which is an integer count. This value represents the number of block parameters that could be referenced by the child template. Parameters beyond this cound will never be referenced and can safely be omitted by the helper if desired. This is optional and any additional parameters passed to the template will be silently ignored.

How can we use multiple helpers inside a single expression?

Handlebars offers support for subexpressions, which allows you to invoke multiple helpers within a single mustache, and pass in the results of inner helper invocations as arguments to outer helpers. Subexpressions are delimited by parentheses.

{{outer-helper (inner-helper 'abc') 'def'}}

In this case, inner-helper will get invoked with the string argument 'abc', and whatever the inner-helper function returns will get passed in as the first argument to outer-helper (and 'def' will get passed in as the second argument to outer-helper.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License