Q:

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?

A:

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:

Fix your template to do something sensible (such as show a loading... message of some sort) if activities is empty.
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.

