How to render and append sub-views in Backbone.js

Ian Storm Taylor picture Ian Storm Taylor · Feb 14, 2012 · Viewed 72k times · Source

I have a nested-View setup which can get somewhat deep in my application. There are a bunch of ways I could think of initializing, rendering and appending the sub-views, but I'm wondering what common practice is.

Here are a couple I've thought of:

Answer

Lukas picture Lukas · Jun 22, 2012

I have generally seen/used a couple of different solutions:

Solution 1

var OuterView = Backbone.View.extend({
    initialize: function() {
        this.inner = new InnerView();
    },

    render: function() {
        this.$el.html(template); // or this.$el.empty() if you have no template
        this.$el.append(this.inner.$el);
        this.inner.render();
    }
});

var InnerView = Backbone.View.extend({
    render: function() {
        this.$el.html(template);
        this.delegateEvents();
    }
});

This is similar to your first example, with a few changes:

  1. The order in which you append the sub elements matters
  2. The outer view does not contain the html elements to be set on the inner view(s) (meaning you can still specify tagName in the inner view)
  3. render() is called AFTER the inner view's element has been placed into the DOM, which is helpful if your inner view's render() method is placing/sizing itself on the page based on other elements' position/size (which is a common use case, in my experience)

Solution 2

var OuterView = Backbone.View.extend({
    initialize: function() {
        this.render();
    },

    render: function() {
        this.$el.html(template); // or this.$el.empty() if you have no template
        this.inner = new InnerView();
        this.$el.append(this.inner.$el);
    }
});

var InnerView = Backbone.View.extend({
    initialize: function() {
        this.render();
    },

    render: function() {
        this.$el.html(template);
    }
});

Solution 2 may look cleaner, but it has caused some strange things in my experience and has affected performance negatively.

I generally use Solution 1, for a couple of reasons:

  1. A lot of my views rely on already being in the DOM in their render() method
  2. When the outer view is re-rendered, views don't have to be re-initialized, which re-initialization can cause memory leaks and also cause freaky issues with existing bindings

Keep in mind that if you are initializing a new View() every time render() is called, that initialization is going to call delegateEvents() anyway. So that shouldn't necessarily be a "con", as you've expressed.