I did some reading and learned that fetching a collection triggers the reset event for the collection and change event for existing model that changed.
In my backbone app, I fetch a collection and various relations (pages -> partials -> variables). But when I do, the change event is triggered for partials and variables, which is not what I want, they are only loaded.. Not changed!
Am I doing something wrong or is this default behavior?
After some digging in the source, I found out it does. It does a change:[key] event.. I added silent:true to my fetch, so it skips the event triggers.
Related
I'm wondering why you need to put a object.on(event, callback, [context]) specifically within an initialize method in backbone, and not somewhere else?
Is it because the initialize method runs automatically -> and the listener starts to listen automatically for that reason?
A better way to design a backbone application is to separate data loading code and views construction.
This can be done by using a separate controller(A custom javascript object) that does the data load part i.e, initializing your models or collections. The controller loads the data (models/collections) necessary for a particular view.
The view instance is then created. Data required for the view can be passed as parameters to the view. One of the better ways is to pass it to use the initialize method which gets invoked automatically during the instantiation of the view.
Also we will expect the view to reflect the changes that model/collection undergoes. Its good to define what events of the model/collection that must be listened to in the intialize method since:
You know that it will be called for sure.
You know for sure that the event binding will be set, since you can reach a view from more than one way like thru a route or a click event on tabs for instance (though better designing is that you have a center piece of code which handles all the ways you reach a view).
Also set the rules for event bindings during the initialization itself.
You can also refer to the below link that talks about decoupling view from data loading.
Should the backbone router or view handle fetching data and displaying loading status?
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.
I construct a CompositeView by passing it a collection. The collection gets its data via a url. I'm using the defer/promise technique to wait till the collection is populated before constructing the View.
Later I call fetch on the collection again, modifying the url.
To my surprise the CompositeView is re-rendered with the new data in the Collection. I thought I would have to do something e.g.:
collectionEvents: {
"sync" : "render"
}
But I'm not doing anything. No event binding at all. I thought in marionette I would have to handle this 'manually'.
This looks like something to do with CollectionView: Automatic Rendering. Does this happen with models and item views as well? And why do some tutorials etc. explain about binding?
Thanks
--Justin Wyllie
Yes but the only thing that will be re-rendered will be the collection, if you are using a CompositeView to display a model and a collection, the model part will not be re-rendered, you have to set an event for that.
So the CompositeView has the same behavior of the collectionView and it will re-render the collection whenever theres a change in the data.
And to your second question this does not happens in the ItemViews when the model changes.
this you have to do it on your own when its best for you application needs.
I am using backbone + stickit to give me 2 way bindings between my views and models but have come up against some issues.
How to keep the model up to date with the server?
I have setup my collection to call fetch() every 60 seconds. This gets the latest version of the models from the server and 'intelligently merges' them. But, I am still seeing local changes overwritten. If I have entered some text in a textbox (which is correctly bound using stickit), the changes from the server overwrite the local changes.
How to update the server when the view changes?
Stickit emits a change event on the model when an attribute is changed, but change events are also triggered when attributes on the server have changed. Where is the best place to call model.save() so its only called when stickit emits a change event?
You can save model on every model change event (bad idea)
You can try to fetch model with the silent option and then just trigger change event on some attributes if needed (better idea)
Set updateView to false http://nytimes.github.io/backbone.stickit/#bindings/updateview (good idea)
I'm new to backbone and am a bit stuck. Basically I want to update a collection on the change of a select. Currently on the change of the select I call Collection.fetch() but this appends the new models in the view. I was under the impression that when fetch is called, it removes the previous models which should then cause the related views to be removed, or am I incorrect?
Any help is appreciated!
It does by default, unless you've specified {add: true}.
The reason that the elements are being appended in the view will be because you are appending them without clearing out the old. When the reset event is fired in your view you could consider emptying your container before appending.
Remember, with backbone you are handling the DOM manipulation yourself. The View is not automagically updated along with your Collections & Models.