Handlebars.js

Handlebars.js templates are also considered logic-less and are largely based on Mustache templates, but provide some additional features. They also exclude some of the features of Mustache templates that the creators did not consider useful.

Handlebars is one of the more prominent templating engines in the JavaScript community. It is used by several major open source JavaScript frameworks including Backbone.js, Ember.js, and the popular Meteor.js framework. It uses their own reactive flavor of Handlebars templating engine called Spacebars. Due to its popularity, we will cover Handlebars in a bit more depth here.

Explicit path lookup versus recursive path lookup

One of the features that differentiates Handlebars templates from Mustache templates is that Handlebars does not support recursive path lookup as Mustache templates do. This concerns sections, or blocks, as they are referred to in Handlebars. When you are in the context of a child property of an object, Handlebars will not automatically look up the scope chain for an expression reference. Instead, you must explicitly define the path to the scope for the variable that you are looking for. This makes the scope in Handlebars templates more meaningful and understandable:

{ 
    "name": { 
        "first": "Peebo", 
        "last": "Sanderson" 
    }, 
    "email_subscriber": false, 
    "age": 54, 
    "profession": "Singer" 
} 

Given this object, the following template syntax would work with Mustache templates:

<!-- Mustache template --> 
<p>{{name.first}} {{name.last}}</p> 
{{#profession}} 
<p>Profession: {{profession}}</p> 
{{/profession}} 

This template would render the value for the profession key inside of the block scope for #profession because Mustache supports recursive path lookup. In other words, a nested context always has access to variables on the parent context above it. This is not the case by default, however, with Handlebars:

<!-- Handlebars template --> 
<p>{{name.first}} {{name.last}}</p> 
{{#profession}} 
<p>Profession: {{this}}</p> 
{{/profession}} 

As shown in this example, the this keyword is used to reference the variable for which the current block context is set. If the profession variable itself were referenced, this would throw an error in Handlebars.

<!-- Handlebars template --> 
<p>{{name.first}} {{name.last}}</p> 
{{#profession}} 
<p>Profession: {{../profession}}</p> 
{{/profession}} 

Additionally, Handlebars can look up the scope chain for a variable with an explicit path reference using the ../ syntax shown in the preceding code. This syntax mimics that of recursive file path lookups in command-line interfaces. In this example, the ../profession reference simply looks up the variable for which the current block context is set:

<p>Peebo Sanderson</p> 
<p>Profession: Singer</p> 

The reason Handlebars does not support recursive path lookup by default is for speed. By limiting the path lookup to the current block context, Handlebars templates can render more quickly. A compile time compat flag is provided to override this functionality and allow recursive path lookups, but the creators of Handlebars advise against this and note that there is a performance cost in doing this.

Helpers

Handlebars templates do not support the use of lambdas defined in objects such as Mustache templates, but instead use helpers for added functionality. Helpers in Handlebars are a way to abstract away view logic that might otherwise be done directly in the templates when using a less restrictive templating engine such as Underscore.js. Instead, you can write a helper in the form of a regular JavaScript function, register it on the Handlebars namespace, and in your template, use it as a single expression or a block expression:

 
{ 
    "name": { 
        "first": "Udis", 
        "last": "Petroyka" 
    }, 
    "age": "82" 
} 
 

Given this example object, a helper can be written to return the user's full name based on the object properties:

Handlebars.registerHelper('fullName', function(name) { 
    return name.first + ' ' + name.last; 
}); 

As shown here, the Handlebars object provides a registerHelper method that gives you the ability to define a helper by defining the name as the first argument and a lambda as the second argument. Arguments to the lambda can be provided directly from the template context at the point the helper is invoked; in this case, as an expression:

<p>Hi, my name is {{fullName name}}.</p> 

The syntax for the helper, as shown in the preceding example, uses the name of the helper immediately following the opening Handlebars tags followed by any arguments to be passed to the helper; in this case, the name argument:

<p>Hi, my name is Udis Petroyka.</p> 

The template would then be rendered as HTML with the full name returned from the helper by passing the required object property from the template context.

Helpers as block expressions

Handlebars templates use block expression syntax to invoke helpers as well. The context for the block expression, however, is entirely dependent upon the way the helper is written. Several built-in block helpers are provided with Handlebars.

#if block helper

A simple #if block helper is provided with Handlebars for rendering content or not based on Boolean values or truthy versus falsy value resolution. This means that values such as 0, null, undefined, and empty lists [] will resolve as false.

Consider the following object:

{ 
    "name": { 
        "first": "Jarmond", 
        "last": "Dittlemore" 
    }, 
    "email_subscriber": false 
} 

Rather than using the standard Mustache style section implementation, the #if helper can be invoked on a Boolean value here:

<p>{{name.first}} {{name.last}}</p> 
{{#if email_subscriber}} 
    <p>I am an email subscriber.</p> 
{{/if}} 

This template would not render the portion inside of the #if block because email_subscriber is false. The built-in #if helper also provides the ability to include an {{else}} section within the #if block that will render if the passed variable evaluates to false:

<p>{{name.first}} {{name.last}}</p> 
{{#if email_subscriber}} 
    <p>I am an email subscriber.</p> 
{{else}} 
    <p>I am not an email subscriber.</p> 
{{/if}} 

Given the example object, this template would render the following:

<p>Jarmond Dittlemore</p> 
<p>I am not an email subscriber.</p> 

Another difference between the #if helper in Handlebars and a section in Mustache templates is that the context inside of the #if helper does not change, whereas the context inside of a section is changed to the object property for which it is called.

#unless block helper

The #unless block helper in Handlebars is similar to the inverted section feature in Mustache templates, and it can also be considered the inverse of the Handlebars #if helper. If the value passed to the #unless helper is falsy, the block will be rendered:

{ 
    "name": { 
        "first": "Chappy", 
        "last": "Scrumdinger" 
    }, 
    "email_subscriber": false 
 
} 

Consider a template similar to the previous #if example and based on the preceding object:

<p>{{name.first}} {{name.last}}</p> 
{{#unless email_subscriber}} 
   <p>I am not an email subscriber.</p> 
{{/if}} 

This template would render the content inside of the #unless block because the value of email_subscriber is false:

<p>Chappy Scrumdinger</p> 
<p>I am not an email subscriber.</p> 

#each block helper

The #each block helper is used to iterate over both lists and objects. In its most basic form, it works just like a Mustache section in the context of a list, but it has additional features that make it much more powerful:

{ 
    "people": [ 
        { "firstName": "Peebo", "lastName": "Sanderson" }, 
        { "firstName": "Udis", "lastName": "Petroyka" }, 
        { "firstName": "Jarmond", "lastName": "Dittlemore" }, 
        { "firstName": "Chappy", "lastName": "Scrumdinger" } 
    ] 
} 

In the #each context for a list, the this keyword can be used to refer to the current value in the list:

<ul> 
{{#each people}} 
    <li>{{this.firstName}} {{this.lastName}}</li> 
{{/each}} 
</ul> 

This is similar to the lambda example of iteration for Mustache templates, except that no lambda property value is needed to access the iterated object properties in this case.

Since the scope for each iteration is constrained to the object that is currently being iterated over in this example, the preceding template could also be more simply written as follows:

<ul> 
{{#each people}} 
    <li>{{firstName}} {{lastName}}</li> 
{{/each}} 
</ul> 

As you can see, the this keyword is not necessary to access the properties for each object since the context for each iteration is set to that object.

#with block helper

The #with block helper works much like a standard section in Mustache templates by constraining the context of the current block to the parent key that is passed in:

{ 
    "name": { 
        "first": "Peebo", 
        "last": "Sanderson" 
    }, 
    "email_subscriber": false, 
    "age": 54, 
    "profession": "Singer" 
} 

Given this example object, a template can be constructed using the #with helper to constrain a block to the context of the name key:

<h1>User Information</h1> 
<dl> 
    <dt>Name</dt> 
    {{#with name}} 
    <dd>{{first}} {{last}}</dd> 
    {{/with}} 
    <dt>Age</dt> 
    <dd>{{age}}</dd> 
    <dt>Profession</dt> 
   <dd>{{profession}}</dd> 
</dl> 

This template would render the following HTML:

<h1>User Information</h1> 
<dl> 
    <dt>Name</dt> 
   <dd>Peebo Sanderson</dd> 
   <dt>Age</dt> 
    <dd>54</dd> 
    <dt>Profession</dt> 
   <dd>Singer</dd> 
</dl> 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.97.170