Simplifying templates with helpers in Handlebars

While writing templates we often have the task of displaying common visual elements, such as alerts, dialogs, and lists. These elements may have a complex internal structure, and writing a template every time to map the model to this structure can be an error-prone and repetitive process.

Handlebars allows us to simplify the writing of templates containing common elements by replacing the template for the common element with a call to helpers.

In this recipe, we're going to write Handlebars helpers to render links, images, and unordered lists. We're going to display a list of people with their name, photo, and link to their profile.

Getting ready

We need to download Handlebars from https://github.com/wycats/handlebars.js. The browser version is in the dist directory. Create a directory for the example and copy handlebars.js to this directory, or download directly (on Linux):

wget https://raw.github.com/wycats/handlebars.js/master/dist/handlebars.js

How to do it...

Follow these steps:

  1. Create index.html, which will contain the list style, list placeholder, and list template. The template will utilize our new helpers:
    <!DOCTYPE HTML>
    <html>
    <head>
    <title>Helpers in Handlebars</title>
    <style type="text/css">
    li { padding:1em; }
    li img { vertical-align:middle; }
    </style>
    </head>
    <body>
    <div id="list">
    </div>
    <script id="template" type="text/x-handlebars-template">
    
    {{#ul list}}
        {{img image alt=name}} {{name}}
    {{else}}
        No items found
    {{/ul}}
    
    </script>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script type="text/javascript" src="handlebars.js"></script>
    <script type="text/javascript" src="example.js"></script>
    </body>
    </html>
  2. Implement the helpers, and render the template in example.js:
    $(function() {    
        Handlebars.registerHelper('ul', function(items, options) {
            if (items .length) return '<ul>' + items.map(function(item) {
                return '<li>' + options.fn(item) + '</li>';  
            }).join('') + '</ul>'
            else
                return options.inverse(this);
        });
    
        Handlebars.registerHelper('img', function(src, options) {
            return new Handlebars.SafeString('<img src="' + src
                + '" alt="'+ (options.hash['alt'] || '')
                + '" title="'+ (options.hash['title'] || '')
                + '">'),
        });
    
        var template = Handlebars.compile($('#template').html());
    
        $('#list').html(template({list:[
            { name: 'John',  image: '1.png'},
            { name: 'Jack',  image: '2.jpg'},
            { name: 'Jenny', image: '3.jpg'},
        ]}));
    });

How it works...

Inside our template, we're using two new helpers, ul to display lists and the img tag to display images.

Handlebars has two different types of helpers: regular and block. Block helpers are invoked in the following format:

{{#helperName argument param=value otherparam=value}}
    body
{{else}}
    alternative
{{/name}}

When Handlebars encounters a block, it invokes its block function, which takes one or two arguments:

function helper(argument, options) {
…
}

If specified, the first argument is passed to the helper function. If the first argument is not available, the options argument becomes first.

The named parameters are also optional, and are available inside the options argument in the hash property that is, options.hash.

Next comes the mandatory block argument, available inside the helper function as options.fn. The block argument is a function that takes a context and returns the result of rendering the block with that context

The else block is also a block function (options.inverse). It is optional and can be omitted. If omitted, a default empty block function is passed as options.inverse instead.

In our example we pass the list contents to our ul helper. This helper uses the regular block on each item if there are items in the list; otherwise it uses the alternative block to display the empty list message.

The other type of helper is a regular helper and can be invoked as follows:

{{helperName argument param=value otherparam=value}}

Normal helpers work similarly, to the block helpers, except that they don't receive the block parameters. In our example, we pass the alt text to the rendered image as a named parameter.

Both types of helpers should return the rendered HTML.

In our example.js file, we register our two new helpers by calling Handlebars.registerHelper. This makes them available to all subsequent templates that we need to render. Afterwards, we can call render on the template with our data, which in turn invokes the helpers to generate the resulting HTML:

<ul>
    <li> <img src="1.png" alt="John" title=""> John </li>
    <li> <img src="2.jpg" alt="Jack" title=""> Jack </li>
    <li> <img src="3.jpg" alt="Jenny" title=""> Jenny </li>
</ul>
..................Content has been hidden....................

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