Backbone Collection Update

Jeremy Gayed
On Frontend Engineering
2 min readOct 2, 2012

--

Recently, while working on a Backbone-driven UI, I had the need to update a collection with two separate pieces of source data. That is, on initial load, I would get the basic properties of each Model in a Collection (color, title, etc) and later on during the lifetime of the app, I would get updates to the status of the Model along with other additional properties and potentially a completely new set of models. There was also the possibility that the basic properties would come in after the auxiliary properties due to latency and other factors.

There are likely many ways to solve this problem, but the first thing I looked for was an update() method on Backbone Collections. Surprisingly, Backbone Collections do not have an update() method out of the box and other solutions would require maintaining IDs, or reference hashes, etc. — things I preferred to avoid so as not to have to maintain. So, I set out to make my own update() method and attach it to the Backbone.Collection.prototype chain.

Here is what I started with:

Backbone.Collection.prototype.update = function(col_in){  
var self = this;
_(col_in).each(function(mod_in) {
var new_model = self._prepareModel(mod_in);
var mod = self.get(new_model.id);
if (mod) { mod.set(mod_in); } else { self.add(mod_in); }
});
};

What this is basically doing is that for each model, mod_in, in the collection set coming in (col_in) we instantiate a new_model object (in order to attach the appropriate Backbone.Model properties). We then grab (via the Collection.get() method) any models that already exist in the collection, mod. If the model already existed, we simply update its data using the set() method. If it doesn't exist, we add() it to the collection.

The issue with that loop is that it does not properly handle "stale" models. That is, it does not remove models that were not passed in as part of the collection to the update() method.

Easy to fix, we just need to create a new array of models and only add those that existed previously or are new to the collection (discarding those that were not passed into the update() method). See below:

Backbone.Collection.prototype.update = function(col_in){  
var self = this,
new_models = [];
_(col_in).each(function(mod_in) {
var new_model = self._prepareModel(mod_in),
mod = self.get(new_model.id);
if (mod) {
new_models.push(mod.set(mod_in, {silent:true}));
} else {
new_models.push(mod_in);
}
});
this.reset(new_models);
};

Here's a gist of this piece of code. Hopefully it will be included as part of the Backbone.js core eventually, as I think this is a method that may get a lot of utility in more complicated applications.

--

--

Coptic Orthodox Christian. Lead Software Engineer @nytimes. Lover of all things JavaScript 🤓