Radu
Radu

Reputation: 8699

Backbone collection add method being fired twice

For the following code, the add event bound in the view fires twice (more if you add more elements to the collection at once).

http://jsfiddle.net/radu/GnG66/

App = window.App || {};

var Model = Backbone.Model.extend();
var Collection = Backbone.Collection.extend();
App.collection = new Collection({ model: Model });

var View = Backbone.View.extend({
    events: {
        'click': function() {
            console.log('click');
            App.collection.add([{
                foo: 'foo'
            }, {
                bar: 'bar'
            }]);
        }
    },
    initialize: function() {
        App.collection.on('add', function() {
            console.log('Something has been added to the collection')
        }, this);
    }
});

$(function() {
    App.view = new View({ el: '#test' });
});​

If instead of adding an array to the collection, you just pass several objects as arguments (basically just remove the square brackets), the event only fires once.

Is this by design and is there a way to override this behaviour without passing { silent : true } as an option?

Upvotes: 4

Views: 2535

Answers (2)

brokethebuildagain
brokethebuildagain

Reputation: 2191

Sorry to resurrect this question from the dead, but I was having this problem too and wanted to post how I solved it. The problem with having 'add' trigger so many times for me was because I had a complex render function in my view that was listening for 'add'. This was causing serious performance issues.

I resolved it by creating a temporary collection using backbone's handy collection.clone() method on it, adding the new models to it, and then resetting the original collection with the temp collection's models property. The code looks like this:

// Create a temporary copy of searchResults
var temp = App.searchResults.clone();

// Add the new results
temp.add(newResults.models);

// Copy the new data over the old data
App.searchResults.reset(temp.models);

// Added this since reset triggers 'reset' and my view is listening for 'change add remove'
this.get('filtered_flights').trigger('change');

This sets off only ONE 'change' event instead of several 'add' events.

Upvotes: 1

Jamison Dance
Jamison Dance

Reputation: 20184

The add event is fired once for each model added.

Collection.add can take an array of models, or a single model and some options.

In your example above, you are passing an array of two models in. Since the add event gets fired once for each model added, it fires twice.

When you pass in several objects, Backbone thinks the first object is a model and the second is a hash of options. That means only one model is being added, so it fires the add event once.

Upvotes: 3

Related Questions