When a item of collection changed, collections "change" trigger is fired or not? If not should i bind them myself? Do anybody give me an example about this?
the change event is fired every time a model's attributes are changed. this event fires for the model itself and for any collection the model belongs to.
someCollection.bind("change", function(model, attributes){
// do something with the model, here
});
Related
Is there a way to gather more information about the changes from within the Backbone.JS collection change event. What I would like to figure out is whether or not it possible to to know what the collection change was; was a model updated, was one added or removed from the collection and also, for every of these, figure out which one.
Different events
When model is added to collection
collection.on('add',this.someFunc,this);
When a model is removed from a collection.
collection.on('remove',this.someFunc,this);
There is no change event on collection but you need to listen on models change event for change
in model:
initialize:function(){
this.on('change',function(){
this.collection.trigger('change');
});
}
Now on collection you can hear for change event
collection.on('change',this.someFunc,this);
refer this for list of all backbone built-in events
triggering the model.destroy() triggers a delete request to the server and server sents back success:true, I have an event listener on the view.model listening on destroy. after all this I can still see the model still exist on the view. and the collection also doesn't remove the model..
Updated ...
this happens only after updating the model and calling on delete on it again. if the model was there during loading it would be delete but the view still hold a link to the model. so the model is really not made null/destroyed
I think view will not get removed from DOM, when you remove the model that used to render the view. You have to add some listener to remove view when model is removed.
view.listenToOnce(view.model, 'destroy', function(){
view.remove();
})
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.
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.
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);
}
})
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.
When you look into the source code of Backbone.js, version 0.9.2, there is
"_onModelEvent":
This method is responsible of forwarding events from the model to the collection (bubbling up).
So when you change something in a model which is part of a collection (with "set"), there is a change event, and because (in the add method) the _onModelEvent method was bound to the model ("all"), this method gets called.
I also see, that there is a destroy method, which triggers a "destroy" event.
But why does the author (in the first line of the _onModelEvent) check, if the event name is "add" or "remove". Normally there is no "add" event on the model?
I do not understand this.
Can somebody explain it to me?
Thanks in advance
_onModelEvent: function(event, model, collection, options) {
if ((event == 'add' || event == 'remove') && collection != this) return;
With Backbone you can create nested model structures and collections. So you can create a collection where the model is a collection. That is way the check in place:
So from the annotated source:
_onModelEvent:
Internal method called every time a model in the set fires an event.
Sets need to update their indexes when models change ids. All other
events simply proxy through. "add" and "remove" events that originate
in other collections are ignored.
So if you have a collection as a model. It won't delegate the add or remove event if items were added/removed to/from the child collections because in that case only the child collection is changed and not the parent.
I have a Backbone Collection initialized by running collection.fetch() method, and then after a while, I asked the collection to fetch again in order to refresh the models. so, is there any event from Model fired that I can subscribe from View in order to remove/update the view.
There isn't a specific "the collection has been refetched" event but you don't need one. fetch resets the collection:
fetch collection.fetch([options])
[...]
When the model data returns from the server, the collection will reset.
And reset triggers a "reset" event:
reset collection.reset(models, [options])
[...]
Use reset to replace a collection with a new list of models (or attribute hashes), triggering a single "reset" event at the end.
So just listen for "reset" events from the collection and re-render the view when you get one.
The behavior of fetch changed in Backbone 1.0, from the ChangeLog:
Renamed Collection's "update" to set, for parallelism with the similar model.set(), and contrast with reset. It's now the default updating mechanism after a fetch. If you'd like to continue using "reset", pass {reset: true}.
And if we look at set:
set collection.set(models, [options])
The set method performs a "smart" update of the collection with the passed list of models. If a model in the list isn't yet in the collection it will be added; if the model is already in the collection its attributes will be merged; and if the collection contains any models that aren't present in the list, they'll be removed. All of the appropriate "add", "remove", and "change" events are fired as this happens.
So you can say collection.fetch({ reset: true }) if you want to keep using the "reset" event or you can collection.fetch() and listen for individual "add", "remove", and "change" events.