Handlebars.js Block Helpers

Keywords: Handlebars JSON

Block-level Helpers can customize iterators and other helpers in a new data context.

Basics

Next, define a simple block-level Helpers

<divclass="entry">
<h1>{{title}}</h1>
<divclass="body">
    {{#noop}}{{body}}{{/noop}}
</div>
</div>

noop helper accepts an option hash, which contains a function (option.fn), which accepts a data context and returns a string just like a common compiled template.

Handlebars.registerHelper('noop',function(options){
return options.fn(this);
});

Handlebars can call the current data context through this.

The with helper

Based on the noop helper, the use of with helper is obvious. With helper, we can restrict any data context.

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

This helper is very useful when your JSON contains many important attributes. You need to repeat the parent's name all the time, such as using the following context

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

with helper is very similar to noop above. Accept a parameter and render it to the {{mustache}} block.

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

iterator

One of the most common uses of block-level helpers is custom iterators. In fact, all built-in helpers are the same as block-level helpers. Let's take a look at how the built-in each helper works.

<divclass="entry">
<h1>{{title}}</h1>
  {{#with story}}
<divclass="intro">{{{intro}}}</div>
<divclass="body">{{{body}}}</div>
  {{/with}}
</div>
<divclass="comments">
  {{#each comments}}
<divclass="comment">
<h2>{{subject}}</h2>
      {{{body}}}
</div>
  {{/each}}
</div>

In the example above, we loop through 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;
});

Pass in the data context, loop through them, generate a string, and return.
Now, it's easy to see how to implement more complex iterators. For example, generate a

    list

{{#list nav}}
<ahref="{{url}}">{{title}}</a>
{{/list}}
//Use the following data
{
  nav:[
{ url:"http://www.yehudakatz.com", title:"Katz Got Your Tongue"},
{ url:"http://www.sproutcore.com/block", title:"SproutCore Blog"},
]
}

Listhelper is different from native 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>";
});

Conditional judgement

Another common application is conditional judgment. Similarly, the built-in if and unless are implemented as a block-level helper.

{{#if isActive}}
<imgsrc="star.gif"alt="Active">
{{/if}}

The control structure usually does not change the current data context, but it determines whether to render the corresponding block based on some variables.

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

When using conditional judgment, it is often necessary to insert corresponding HTML blocks when judging the result is false. Handlebar uses else to solve this problem.

{{#if isActive}}
<imgsrc="star.gif"alt="Active">
{{else}}
<imgsrc="cry.gif"alt="Inactive">
{{/if}}
Handlebar Use options.inverse To generateelseContent, if not inverse Function, the template automatically creates an empty function.
Handlebars.registerHelper('if',function(conditional, options){
if(conditional){
return options.fn(this);
}else{
return options.inverse(this);
}
});

Hash parameter

Like a normal helper, a block-level helper can accept a hash as the last parameter. Let's improve the list helper, so that

    Accept any number of attributes.

{{#list nav id="nav-bar" class="top"}}
<ahref="{{url}}">{{title}}</a>
{{/list}}
Handlebar Take last hash Pass to opton.hash,This allows arbitrary parameters to be accepted if the template is not passed hash Parameters, option.hash Would be{}. 
Handlebars.registerHelper('list',function(context, options){
var attrs =Em.keys(options.hash).map(function(key){
    key +'="'+ options.hash[key]+'"';
}).join(" ");

return"<ul "+ attrs +">"+ context.map(function(item){
return"<li>"+ options.fn(item)+"</li>";
}).join("\n")+"</ul>";
});

Block-level Helper can also pass private variables so that data outside the data context can be passed in.
For example, we generate a list containing the ordinal number of the current column.

{{#list array}}
  {{@index}}. {{title}}
{{/list}}
Handlebars.registerHelper('list',function(context, options){
var out ="<ul>", data;

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

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

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

Pass private variables through data.

Blank handling

Use ~to omit whitespace on either side of the template

{{#each nav ~}}
<ahref="{{url}}">
    {{~#if test}}
      {{~title}}
    {{~^~}}
      Empty
    {{~/if~}}
</a>
{{~/each}}
//Use the following data
{
  nav:[
{url:'foo', test:true, title:'bar'},
{url:'bar'}
]
}

Result output without line breaks and spaces

<a href="foo">bar</a><ahref="bar">Empty</a>

Posted by wyrd33 on Thu, 11 Apr 2019 21:33:31 -0700