Better Templating with Partials in Handlebars and BackboneJS

One common problem that we face during BackboneJS is view management. Things are simpler when you are developing single page application. But when it comes to multi-page application in BackboneJS, it is common that views become unmanageable. Consider a situation where you are developing a mobile application in BackboneJS with multiple screens. Now you want that the header and footer should remain same throughout the application. There may be several strategies to handle this situation. Note that we have used Handlebars as templating system and the text plugin for reading templates.


Approach 1

The simpler way is that you can create two templates for header and footer and use them in all of your views. For example on your view you can write something like:
var page1 = Backbone.View.extend({
    template: Handlebars.compile(require("text!templates/page1.html")),
    render: function () {
        var header_tpl = Handlebars.compile(require("text!templates/header.html"));
        var footer_tpl = Handlebars.compile(require("text!templates/footer.html"));
        
        this.$el.html(_self.template());
        $("body .main").html(_self.$el);

        //Add header and footer to body
        $("body .header").html(header_tpl);
        $("body .footer").html(footer_tpl);
    }
});
So what's wrong with this approach? I would say nothing. But think that you may have a lot of pages in your application and in each view's render() function you will have to include the header and footer code. Moreover the html of header and footer is not a part of the main view page. So their content will not be available inside view's $el object. You will not be able to add event handlers to header and footer in the view's events object.

Approach 2: Using Partials

In this approach which I would prefer, we will create partials in Handlebars. These partials will be used in the templates and we need not to change anything in our view. Here is how to create partials using Handlebars and Backbone. In your app.js you can declare partials like:
define(function (require) {
    //Define the header and footer partials for the Handlebars
    //User these partials as {{>header}} anywhere in the templates
    var header = Handlebars.compile(require("text!templates/header.html"));
    Handlebars.registerPartial('header', header);

    var footer = Handlebars.compile(require("text!templates/footer.html"));
    Handlebars.registerPartial('footer', footer);
});


In your template use these partials as:
File page1.html:
{{>header}}

    <div class="content"></div>

{{>footer}}

File header.html:
<div class="header">Header</div>

File footer.html:
<div class="footer">Footer</div>

Now in your view, you can write:
var page1 = Backbone.View.extend({
    template: Handlebars.compile(require("text!templates/page1.html")),
    render: function () {
        this.$el.html(_self.template());
        $("body .main").html(_self.$el);
        
        //header HTML is available inside $el of this view
        //$header = this.$(".header");
    }
});


Benefits of this approach: 

  1. No need to add extra code in views. 
  2. You just need to change the templates. 
  3. The content of partials is available in the $el of the parent view. 
  4. Easy code management as views need not be altered when there is change in templates. 
  5. You can add event handlers on the partials added this way.


If you have a better solution, we can discuss that in comments :)

We would love to hear from you...

back to top