Note that fetch should not be used to populate collections on page load — all models needed at load time should already be bootstrapped in to place. fetch is intended for lazily-loading models for interfaces that are not needed immediately: for example, documents with collections of notes that may be toggled open and closed.
There is a section on loading bootstrapped models but to me it was as clear as mud. After a bit of trial and error I worked out how to load bootstrapped data and created this JSFiddle to show it.
I'm omitting all of the RESTful parts of the code for this example.
Lets get started with the template definition. This is inside the main page HTML...
HTML
<script type="text/template" id="item-template">
<%- id %> - <%- name %>
</script>
Nothing fancy there, the template displays the 'id' and 'name' attributes from the model. Next is the basic definition of the model, collection and model view.
JavaScript
var ItemModel = Backbone.Model.extend({});
var ItemCollection = Backbone.Collection.extend({
model: ItemModel
});
var ItemView = Backbone.View.extend({
tagName: 'div',
template: _.template($('#item-template').html()),
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
Again, nothing fancy here, just some stock standard Backbone.js code. The collection is defined for the model and the view is defined for the same model. The view uses the previously defined template to create an element and populate it from its model.
Next is the bootstrap data. This is defined in the HTML body...
HTML
<script>
bootstrapData = [
{id: 1, name: 'Test 1'},
{id: 2, name: 'Test 2'},
{id: 3, name: 'Test 3'}
];
</script>
How this data gets into the HTML body is up to you. In my case I was looking up my data in the PHP side of the application. Then, I was converting the looked up data into a string representation of a JSON array and assigning it to a Smarty template. The Smarty template then was rendered with all the data ready to be consumed by the JavaScript side of the application.
The main point here is to have the bootstrap data defined as a JavaScript array with hashes of your models contained within it.
Moving onto the code that defines the application view. This is where the 'magic' happens...
JavaScript
var items = new ItemCollection();
var AppView = Backbone.View.extend({
el: '#content',
initialize: function() {
this.listenTo(items, 'reset', this.addAll);
items.reset(bootstrapData);
},
addAll: function(collection, options) {
this.$el.children().remove();
for (i = 0; i < collection.length; i++) {
var model = collection.at(i);
var itemView = new ItemView({ model: model });
this.$el.append(itemView.render().el);
}
}
});
var app = new AppView();
In the initialize() function I add a listener for the 'reset' event that calls the addAll() function. Immediately after I call reset() on the collection passing in the bootstrap data that was defined earlier.
In the addAll() function I first remove all of the previous contents of the app view containing element. This is important in case the collection reset is triggered multiple times since we don't want to show duplicate data. Afterwards I loop over the collection getting each model, creating its corresponding view and then appending it to the app view containing element.
That last part where I loop over the collection and create new model views was something that wasn't clear to me after reading Backbone.js documentation. The final code is really straight forward but it did take me a bit of experimentation to get there (I'm not a frond end developer after all!)
Don't forget to add a div to the page HTML to contain the app elements...
HTML
<div id="content"></div>
That's it! Good luck!
-i