Reputation: 482
I'm having some trouble getting change events to fire when a model is updated via polling of an endpoint. I'm pretty sure this is because the collection is not actually updated. I'm using the new option (update: true
) in Backbone 0.9.9 that tries to intelligently update a collection rather than resetting it completely.
When I insert a console.log(this)
at the end of the updateClientCollection
function, it appears that this.clientCollection
is not updating when updateClientCollection
is called via setInterval
. However, I do see that the endpoint is being polled and the endpoint is returning new and different values for clients.
managementApp.ClientListView = Backbone.View.extend({
className: 'management-client-list',
template: _.template( $('#client-list-template').text() ),
initialize: function() {
_.bindAll( this );
this.jobId = this.options.jobId
//the view owns the client collection because there are many client lists on a page
this.clientCollection = new GH.Models.ClientStatusCollection();
this.clientCollection.on( 'reset', this.addAllClients );
//using the initial reset event to trigger this view's rendering
this.clientCollection.fetch({
data: {'job': this.jobId}
});
//start polling client status endpoint every 60s
this.intervalId = setInterval( this.updateClientCollection.bind(this), 60000 );
},
updateClientCollection: function() {
//don't want to fire a reset as we don't need new view, just to rerender
//with updated info
this.clientCollection.fetch({
data: {'job': this.jobId},
update: true,
reset: false
});
},
render: function() {
this.$el.html( this.template() );
return this;
},
addOneClient: function( client ) {
var view = new managementApp.ClientView({model: client});
this.$el.find( 'ul.client-list' ).append( view.render().el );
},
addAllClients: function() {
if (this.clientCollection.length === 0) {
this.$el.find( 'ul.client-list' ).append( 'No clients registered' );
return;
}
this.$el.find( 'ul.client-list' ).empty();
this.clientCollection.each( this.addOneClient, this );
}
});
managementApp.ClientView = Backbone.View.extend({
tagName: 'li',
className: 'management-client-item',
template: _.template( $('#client-item-template').text() ),
initialize: function() {
_.bindAll( this );
this.model.on( 'change', this.render );
},
render: function() {
this.$el.html( this.template( this.model.toJSON() ) );
return this;
}
});
Upvotes: 0
Views: 234
Reputation: 5454
From what I can gather from your code, you're only binding on the reset
event of the collection.
According to the docs, Backbone.Collection
uses the .update()
method after fetching when you pass { update: true }
as part of your fetch options.
Backbone.Collection.update()
fires relevant add
, change
and remove
events for each model. You'll need to bind to these as well and perform the relevant functions to update your UI.
In your case, you could bind to your existing addOneClient
method to the add
event on your collection.
In your ClientView
class, you can bind to the change
and remove
events to re-render and remove the view respectively. Remember to use listenTo()
so the ClientView
object can easily clean-up the events when it remove()
's itself.
Upvotes: 0