Dan0
Dan0

Reputation: 529

Backbone: firing an event only once on a Collection 'change'

Simple question: What is the best way to fire an event 'only once'?

I have a Collection in backbone with multiple models. Sometimes multiple models' attributes are updated at once, firing multiple 'change' events on the Collection.

What is the best way to fire the 'change' event only once, grouping all attribute changes together?

My best idea at the moment is using a timer but this will only capture the first model attribute change.

All suggestions, ideas and solutions are valued. Thank you :).


Context: In this case the event fires a very computationally intensive function, therefore multiple runs must be avoided.

Upvotes: 5

Views: 2465

Answers (3)

Maksim Sorokin
Maksim Sorokin

Reputation: 2404

You can try resetting the collection, rather than adding the elements. See Collection reset method description:

reset collection.reset([models], [options])

Adding and removing models one at a time is all well and good, but sometimes you have so many models to change that you'd rather just update the collection in bulk. Use reset to replace a collection with a new list of models (or attribute hashes), triggering a single "reset" event at the end. Returns the newly-set models. For convenience, within a "reset" event, the list of any previous models is available as options.previousModels.

As documentation says, if you use reset, instead of add you will get a single reset event in the end.

Upvotes: 2

Stephen Thomas
Stephen Thomas

Reputation: 14053

You can "debounce" the method in your collection that responds to change events, though you'll have to manually figure out which models changed:

Col = Backbone.Collection.extend({
    modelChanged: _.debounce(function() {
        // handle model changes
    }, delayInMs),
    initialize: function() {
        this.collection.on('change', this.modelChanged, this);
    } 
})

Upvotes: 3

Sushanth --
Sushanth --

Reputation: 55750

Whenever you are updating the attributes on the models in bulk, pass {silent:true} as an option, which will suppress any events from being fired.

Then trigger a custom event for which a view or multiple views listening to the same.

Upvotes: 4

Related Questions