Backbone.js Application Walkthrough Part 3: New View and External Templating – Video Tutorial

Backbone Application Walkthrough Part 3: New View and External TemplatingMoving on to part 3 of the Backbone Application Walkthrough video series, we work on moving all of the templates to external files to reduce the dependency on the templates being included in the index.html file and so that they might become available if we use these views on different pages. Also, I added an extra view that wasn't in the original application because, as you'll see in the video, it makes things a little nicer.

Backbone.js Video Tutorial Series

JavaScript Code

I'll just post some of the code on here because it isn't really worth posting all of it. The first line tells you which file it is.

window.StartView = Backbone.View.extend({
    initialize: function() {
        this.template = _.template( tpl.get('start-template') );
    render: function() {
        this.$el.html( this.template() );
        return this.el;
tpl = {

    // Hash of preloaded templates for the app

    // Recursively pre-load all the templates for the app.
    // This implementation should be changed in a production environment. All the template files should be
    // concatenated in a single file.
    loadTemplates:function (names, callback) {

        var that = this;

        var loadTemplate = function (index) {
            var name = names[index];
            console.log('Loading template: ' + name);
            $.get('templates/' + name + '.html', function (data) {
                that.templates[name] = data;
                if (index < names.length) {
                } else {


    // Get template by name from hash of preloaded templates
    get:function (name) {
        return this.templates[name];

Backbone.View.prototype.close = function () {
    console.log('Closing view ' + this);
    if (this.beforeClose) {

tpl.loadTemplates(['header', 'wine-details', 'wine-list-item', 'start'], function () {
    ... // Run App

Backbone.js Video Tutorial Series

Looking Ahead

As I stated in the video, there should be 2 more video left in this series. The next one will be finishing up the application and getting it running. The one after that will be more of a RequireJS tutorial than anything, but will show you how to make your Backbone applications work with AMD. Part 4 should be out this Thursday, so look forward to that. God bless and happy coding!

About the Author

Author: Joe Zim

Joe Zim

Joe Zimmerman has been doing web development ever since he found an HTML book on his dad's shelf when he was 12. Since then, JavaScript has grown in popularity and he has become passionate about it. He also loves to teach others though his blog and other popular blogs. When he's not writing code, he's spending time with his wife and children and leading them in God's Word.

  • María Paulina Ramírez Vásquez

    Hi. It’s great your job. I’m trying apply those examples to my project, but I could not make the pages load properly made ​​as templates. I don’t know what I did wrong, I followed every step as you explain in the video and your project on Github.


    var AppRouter = Backbone.Router.extend({
    routes:{ “”:”menu”, “login”:”login” },
    initialize: function () { // Handle back button throughout the application $(‘.back’).live(‘click’, function(event) { window.history.back(); return false; }); this.firstPage = true; },
    menu: function () { this.changePage(new MenuView()); },
    login: function () { this.changePage(new LoginView()); },
    changePage: function (page) { $(page.el).attr(‘data-role’, ‘page’); page.render(); $(‘body’).append($(page.el)); var transition = $.mobile.defaultPageTransition; // We don’t want to slide the first page if (this.firstPage) { transition = ‘none’; this.firstPage = false; } $.mobile.changePage($(page.el), {changeHash:false, transition: transition}); }});


    window.LoginView = Backbone.View.extend({
    initialize: function() { this.template = _.template(tpl.get(‘login’)); },
    render:function (eventName) { this.$el.html(this.template); return this.el; }});

    window.MenuView = Backbone.View.extend({
    initialize: function() { this.template = _.template(tpl.get(‘menu’)); },
    render:function (eventName) { this.$el.html(this.template); return this.el; }});

    In the $(document).ready:

    Backbone.View.prototype.close = function () { console.log(‘Closing view ‘ + this); if (this.beforeClose) { this.beforeClose(); } this.remove(); this.unbind(); };tpl.loadTemplates([‘login’, ‘menu’], function () { app = new AppRouter(); Backbone.history.start();});

    In the mobileinit:

    $.mobile.ajaxEnabled = false;$.mobile.linkBindingEnabled = false;$.mobile.hashListeningEnabled = false;$.mobile.pushStateEnabled = false;
    // Remove page from DOM when it’s being replaced$(‘section[data-role=”page”]’).live(‘pagehide’, function (event, ui) { $(event.currentTarget).remove();});

    In index.html I have placed the .js necessary, in the recommended order.

    Could you help with this problem? I would greatly appreciate your help.

    • Joe Zimmerman

      Can you send me a link to your entire codebase? Either a webpage that this code is supposed to be running on, or send me a zip file will all of the project’s files enclosed.

      • María Paulina Ramírez Vásquez

        Look at this repo Here is what I worked so far. Thanks for your interest.

      • María Paulina Ramírez Vásquez

        Hi. I found the solution, it seems that the problem was the location of the scripts that were not in the head, were located in the body, and apparently it did not allow load Backbone.history.start (); I appreciate your help :)

        • Joe Zimmerman

          I was just about to take a look at it. I’m glad you figured everything out.

  • Tom

    Fantastic work.

  • bitslayer

    It’s great you lead your wife and children in God’s word…I guess they can’t do it themselves; they need your brilliance. What hubris!
    Article great…but “leading them in God’s word” part of bio sickens me.

    • Joe Zimmerman

      It’s not “hubris”, it’s a mission I’m given as a follower of Christ. If you do not share my faith, then I don’t expect you to understand “For the foolishness of God is wiser than human wisdom, and the weakness of God is stronger than human strength.”