From the exact guide :
fetch collection.fetch([options])
Retrieve the default set of models for this collection from the server, dropping the collection when they arrive. [...] When model data is returned from the server, the collection will be reset.
And what does reset do? reset does the following:
reset collection.reset(models, [options])
[...] Use reset to replace the collection with a new list of models (or attribute hashes), raising one "reset" event at the end.
So fetch calls reset to update the collection models, and reset fires the reset event, not the "change" event. None of the models have changed, and the "change" collections come from their models.
You should have render bound to "reset" :
initialize: function () { this.collection = new ProjectsCollection(); this.collection.bind("reset", _.bind(this.render, this)); this.collection.fetch(...); }
If you want to listen to the "change" events on the contained models, you can bind the "change" handler to the collection with :
You can bind "change" events to receive notifications when any model in the collection has been changed,
[...]
Any event that is fired on the model in the collection will also be fired directly to the collection for convenience.
The collection also generates "add" and "remove" events as the collection itself changes.
Newer versions of Backbone will no longer reset collections during fetch :
When the model data is returned from the server, it uses set to (intelligently) combine the extracted models, unless you pass {reset: true} , in which case the collection will (efficiently) reset.
And set :
[...] performs a smart collection update with a list of models passed in. If the model is not yet assembled in the list, it will be added; if the model is already in the collection, its attributes will be combined; and if the collection contains any models that are not in the list, they will be deleted. All relevant events "add" , "remove" and "change" are fired as it happens
So, with newer versions of Backbone you want to list the events "add" , "remove" and "change" (which in any case should listen to the view based on the collection); you can also use {reset: true} on the initial fetch and listen to "reset" . I would recommend the following approach for collection based views:
- Listen to
"add" and handle this event with a callback that simply adds one element to the view, do not drop everything and do not delay. - Listen to
"remvoe" and handle this event with a callback that only removes the remote model. - Listen to
"change" and handle this with a callback that replaces (or updates) the corresponding item. - Listen to
"reset" and bind it to render . Then pass {reset: true} to the initial call to the fetch collection.
This will capture important events, and presenting the collection will do a minimal amount of work to process each of them. Of course, this strategy does not apply to all situations, but I think this is a good starting point.