Backbone updating views from fetch - backbone.js

I am trying to create a real-time application and there is a collection that I am constantly fetching using setInterval. The problem I am having is that when I fetch my collection Backbone rerenders the whole collection and if I set my fetch interval too short then the events binded to the views associated with the elements in my collection don't fire the click events binded to them reliably (presumably because it was busy rerendering?). How should I structure this?

I'm assuming based on your question that you have a single view rendering your entire collection, bound to the 'sync' event. If instead you create views to render the individual elements of your collection and, on 'sync' iterate through the models in the collection, rendering new ones and updating the views associated with models which have changed you will achieve what I think you want.

Related

How to update the view without re-rendering in marionette.js

How to update the view with the model.fetch(), i.e when i fetch the model, the view shouldn't be destroyed or re-rendered. It should just update the new model into view with reseting the previous model.
this.model.fetch({success: this.render.bind(this)});
This code is re-rendering my view..How can i just update the view with new model
Thanks.
There are multiple ways of updating the view based on your need.
If the view is fairly simple, and all that is needed is to automatically update the view on model's fetch, rendering the view again is the simplest(Backbone's sync event on the model can be used, and model events can be handled declaratively using Marionette View's modelEvents hash -http://marionettejs.com/docs/marionette.view.html#viewmodelevents-and-viewcollectionevents)
modelEvents: {'sync': 'render'}
If you have few model attributes that change in a complex view, you could directly update the dom elements via jquery by listening to change events on the model attributes:
modelEvents: {'change:name':'nameChanged'},
nameChanged: function(model, value){ this.$('#name').val(value);}
If Two way data binding between view and model is needed, frameworks like Backbone.stickit can be used to this purpose - https://github.com/NYTimes/backbone.stickit#usage
Whenever you establish a double binding with your model attributes to the templates, your views need to be rendered again to show the changes. So, you can't avoid rendering to show the updated status of your model.
But what I would suggest you to do is to divide your view into subviews. Since, you are using marionette, you can create a main layout which contains all the regions and for each small region, you can define a view .
For example , suppose I have a basic form with my name, current time and age . All of these variables are stored in a model . So, you have a scenario where your name and age hardly changes but the current time is changing every millisecond causing your whole view to re-render which is bad in terms of performance as well as to the eyes.
So, in order to solve the above scenario, if you could create a separate view for the current-time element, you can render is separately and other elements don't need to be rendered again and again. You can always define a separate view for a single button element if you think that its functionality can be abstracted.

Change details on Backbone.JS collection change event

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

Do CompositeViews automatically re-render when the collection is sync'ed?

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.

Parsing updated collection content, hiding new model view instances

I have a Backbone view which represents a collection. When this collection is synced with the server, and new models are added to the collection, I would like to hide all the view instances that represent these new models in the collection, whilst continuing to display the old models' view instances. How can I do this?
I'm assuming you're using a Marionette.CollectionView or Marionette.CompositeView here, right? That being the case, you are trying to prevent these from showing the newly added models, when the come back from the server and are added to your collection, right?
I can see a few different ways of doing this, most of which begin at the same place: a collection that filters based on an attribute that tells you whether or not to show the model. You would need to have some piece of data on the models that tells you wether to show them or not... I'm not sure what this would look like off-hand, but once you have the logic set up for this, I think the rest of it becomes easier.
A Proxy Collection
My preferred method of handling this in the CompositeView or CollectionView would be to create the view instance with a proxy collection - one that is filtered based on the value to show or hide the models.
I've talked about proxy collections before, and I have a working JSFiddle to show how to build them, here: http://jsfiddle.net/derickbailey/7tvzF/
You would set up a filtered collection like this, and then send the filtered collection to your actual view instance:
var filtered = new FilteredCollection(myOriginalCollection);
filtered.filter({
showThisOne: true
});
var view = new MyCompositeView({
collection: filtered
});
myOriginalCollection.fetch();
From here, it comes down to how you want to manage the filtering and fetch/sync of the original collection. But I think the over-all solution hinges on the proxy/decorator collection and being able to filter the collection down to only the list of items that you want.
Views in Bbone are not automatically updated when the underlying model/collection is changed. You have to explicitly listen for events: change/destroy for models and add/change/remove/reset for collections and call render().
As WiredPrairie suggests, if you've registered during view initialization for example to listenTo() any of these events and explicitly render(), you can always use stopListening() to reverse the effect.
An alternative, in case it's a one-of case of suppressing the view from showing the changes, is to check manually in your view's render() which models have been changed and use the previous state of the changed attributes to avoid showing the new values. Check out: model.hasChanged() and model.previousAttributes() as well as the options.previousModels in case of a collection reset.

Backbone.js - update collection on change of select

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.

Resources