Backbone.js: rendering collections in real world apps

backbone.js

Frustratingly, most ‘tutorial’ examples of backbone.js apps assume a clean model slate. I-.e. that the model collections are empty initially, until a user adds an item. Of course this is not the case in a real world app, where you usually have an existing collection to start with from the back end store.

I would like to know how people deal with existing collections in backbone. Specifically:

  • How do you render a collection after it has been fetched? Is is just a case of iterating through the collection? Should this be trigger by some event?

  • The backbone docs talk about ‘bootstrapping’, which I understand means using data that is available on the initial load (this also makes sense from an SEO point of view). But how does this work in practice? The data is dumped into JS on the server side? Or the JS examines the DOM?

I feel like this is a poor question, but I expect to expand it based on the answers.

EDIT

So it seems that the consensus is to add the data as party of the JS and process that on page load.

One big disadvantage I see with this technique is that the information is not available for search engine spiders. From that perspective it might be better to extract it from the DOM (although I haven't seen anyone do it that way). Or maybe add the HTML server side and stick the data in the JS?

Best Answer

I came across the same situation as you, I don't always want my data bootstrapped initially (especially if its from a third-party api call). I haven't come across any tutorials that do this but looking through the documentation its actually pretty easy. You just need to bind the 'reset' event (this is fired when the entire collection is repopulated) on your collection and render. Heres a quick example:

my_application.js

window.MyApplication = {
  Models: {},
  Collections: {},
  Views: {},
  Routers: {},
  init: function() {
    // Start the data loading
    this.someItems = new MyApplication.Collections.Items();
    this.someItems.fetch();

    // Start rendering the UI before the data is ready
    new MyApplication.Routers.Items(this.someItems);
    Backbone.history.start();
  }
};

routers/items_router.js

MyApplication.Routers.Items = Backbone.Router.extend({
  routes: {
    "" : "index"
  },

  initialize: function(collection) {
    this.collection = collection;
  },

  index: function() {
    var view = new MyApplication.Views.ItemsIndex({ collection: this.collection });
    $('.items').html(view.render().el);
  }
});

views/items/items_index.js

MyApplication.Views.ItemsIndex = Backbone.View.extend({
  initialize: function() {
    _.bindAll(this, "render");

    // Once the collection is fetched re-render the view
    this.collection.bind("reset", this.render);
  },

  render: function() {
    console.log(this.collection.length);
    // Render content
    return this;
  }
});