schleg
schleg

Reputation: 93

Rendering Handlebars template with Backbone

I have a Backbone view (see below) that I believe to be doing the right thing

Index = Backbone.View.extend({
render: function() {
        var activities = new Activities();
        activities.fetch();
        var tpl = Handlebars.compile($("#activities-template").html());
        $(this.el).html(tpl({activities: activities.toJSON()}));
        return this;
      }
});

If execute each line in the render() function with Chrome JS console I get the expected result with the element I pass in getting populated with the template output. However, when I run this using the following

var i = new Index({el: $("body")})
i.render()

"i.$el" is completely empty--the HTML is not getting rendered like it does in console. Any ideas why?

Upvotes: 1

Views: 6344

Answers (1)

mu is too short
mu is too short

Reputation: 434665

fetch is an AJAX call so there's no guarantee that activities.toJSON() will give you any data when you do this:

activities.fetch();
var tpl = Handlebars.compile($("#activities-template").html());
$(this.el).html(tpl({activities: activities.toJSON()}));

Executing the code in the console probably gives the AJAX call time to return with something before you try to use activities.

You should do two things:

  1. Fix your template to do something sensible (such as show a loading... message of some sort) if activities is empty.
  2. Attach your view's render to the collection's "reset" event:

    initialize: function() {
        // Or, more commonly, create the collection outside the view
        // and say `new View({ collection: ... })`
        this.collection = new Activities();
        this.collection.on('reset', this.render, this);
        this.collection.fetch();
    },
    render: function() {
        var tpl = Handlebars.compile($("#activities-template").html());
        this.$el.html(tpl({activities: this.collection.toJSON()}));
        return this;
    }
    

I also switched to this.$el, there's no need to $(this.el) when Backbone already gives you this.$el.

Upvotes: 3

Related Questions