0

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;
  }
});
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
AndrewJesaitis
  • 480
  • 4
  • 15

1 Answers1

0

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.

Cobby
  • 5,273
  • 4
  • 28
  • 41
  • Thanks for the response. I actually do bind those events in the ClientView, but I tried to omit as much code as possible while still providing a test case, sorry if this was confusing. In any case, I don't think the change event is firing because clientCollection which is owned by ClientListView is not being updated, even when I change the models server side, and watch the response from the endpoint in the "Network" tab of the Chrome's Dev tools. I wonder if I'm changing the context (or something else) of the collection when I try to update it using setInterval. – AndrewJesaitis Dec 20 '12 at 17:29
  • Sorry, I missed binding in the view... so you've got models changing but the `change` event isn't being fired? – Cobby Dec 21 '12 at 03:52
  • That's what's odd. The models are not being updated even when the api is return different values. – AndrewJesaitis Dec 21 '12 at 18:33
  • How are you checking the models aren't even being updated? I'm guessing you've probably got it working by now? – Cobby Jan 09 '13 at 00:51