Block helpers make it possible to define custom iterators and other functionality that can invoke the passed block with a new context.
<div class="entry"> <h1>{{title}}</h1> <div class="body"> {{#noop}}{{body}}{{/noop}} </div> </div>
noop helper (short for "no operation") will receive an options hash.
This options hash contains a function (options.fn)
that behaves like a normal compiled Handlebars template.
Specifically, the function will take a context and return a
String.
Handlebars.registerHelper('noop', function(options) { return options.fn(this); });
this, so you can invoke the block with
this to evaluate the block in the current context.
noop on the context object would be referenced using:
{{./noop}}
<div class="entry"> <h1>{{title}}</h1> <div class="body"> {{#bold}}{{body}}{{/bold}} </div> </div>
bold helper will add markup to make its text bold.
As before, the function will take a context as input and return a String.
Handlebars.registerHelper('bold', function(options) { return new Handlebars.SafeString( '<div class="mybold">' + options.fn(this) + '</div>'); });
with helper
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>
{
title: "First Post",
story: {
intro: "Before the jump",
body: "After the jump"
}
}
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); });
each helper works.
<div class="entry"> <h1>{{title}}</h1> {{#with story}} <div class="intro">{{{intro}}}</div> <div class="body">{{{body}}}</div> {{/with}} </div> <div class="comments"> {{#each comments}} <div class="comment"> <h2>{{subject}}</h2> {{{body}}} </div> {{/each}} </div>
each
once for each element in the comments Array.
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; });
<ul> wrapper, and wraps each resulting element
in an <li>.
{{#list nav}} <a href="{{url}}">{{title}}</a> {{/list}}
{
nav: [
{ url: "http://www.yehudakatz.com", title: "Katz Got Your Tongue" },
{ url: "http://www.sproutcore.com/block", title: "SproutCore Blog" },
]
}
each helper.
Handlebars.registerHelper('list', function(context, options) { var ret = "<ul>"; for(var i=0, j=context.length; i<j; i++) { ret = ret + "<li>" + options.fn(context[i]) + "</li>"; } return ret + "</ul>"; });
Handlebars.registerHelper('list', function(context, options) { return "<ul>" + context.map(function(item) { return "<li>" + options.fn(item) + "</li>"; }).join("\n") + "</ul>"; });
if and
unless control structures are implemented as regular
Handlebars helpers.
{{#if isActive}} <img src="star.gif" alt="Active"> {{/if}}
Handlebars.registerHelper('if', function(conditional, options) { if(conditional) { return options.fn(this); } });
else functionality
to block helpers.
{{#if isActive}} <img src="star.gif" alt="Active"> {{else}} <img src="cry.gif" alt="Inactive"> {{/if}}
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.
Handlebars.registerHelper('if', function(conditional, options) { if(conditional) { return options.fn(this); } else { return options.inverse(this); } });
{{#if isActive}} <img src="star.gif" alt="Active"> {{else if isInactive}} <img src="cry.gif" alt="Inactive"> {{/if}}
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.
list helper
and make it possible for us to add any number of optional attributes
to the <ul> element we will create.
{{#list nav id="nav-bar" class="top"}} <a href="{{url}}">{{title}}</a> {{/list}}
options.hash. This
makes it easier to accept a variable number of parameters, while
also accepting an optional Hash. If the template provides no hash
arguments, Handlebars will automatically pass an empty object
({}), so you don't need to check for the existence of
hash arguments.
Handlebars.registerHelper('list', function(context, options) { var attrs = Object.keys(options.hash).map(function(key) { return key + '="' + options.hash[key] + '"'; }).join(" "); return "<ul " + attrs + ">" + context.map(function(item) { return "<li>" + options.fn(item) + "</li>"; }).join("\n") + "</ul>"; });
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; });
data option are
available in all descendent scopes.
index field of the parent iterator, @../index
may be used.
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.
{{#each users as |user userId|}} Id: {{userId}} Name: {{user.name}} {{/each}}
user will have the same value as the current context and userId will have the index value for the iteration.
{{#each users as |user userId|}} {{#each user.book as |book bookId|}} User Id: {{userId}} Book Id: {{bookId}} {{/each}} {{/each}}
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}}
1 2 3 on render.
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 count 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.
{{{{raw-helper}}}} {{bar}} {{{{/raw-helper}}}}
raw-helper without interpreting the content.
Handlebars.registerHelper('raw-helper', function(options) { return options.fn(); });
{{bar}}