nakhli
nakhli

Reputation: 4059

sync event not issued when model is destroyed - Backbonejs

The model collection is not issuing a 'sync' event when a model is destroyed. the documentation seems to say the opposite. here is my code snippet:

var MyModel = Backbone.Model.extend({ id: 1, val: "foo" });
var MyCollection = Backbone.Collection.extend({ model: MyModel, url: '/api/models' });

var myCollection = new MyCollection();

myCollection.on('sync', function () { console.log('synced!'); });
myCollection.on('remove', function () { console.log('removed!'); });

myCollection.fetch(); // => outputs synced!

    // .. wait for collection to load

myCollection.at(0).destroy(); // => outputs removed! but *NOT* synced!        

If I understand well, the doc says the 'destroy' event should bubble up to the collection and issue a 'sync' event. Should the collection in the code above issue a 'sync' event or not?

Upvotes: 3

Views: 2918

Answers (2)

nakhli
nakhli

Reputation: 4059

The 'sync' event is triggered on the destroyed object after being removed from the collection. This is why the collection doesn't fire a 'sync' event. The collection relays the 'destroy' event though.

Upvotes: 7

Paul Hoenecke
Paul Hoenecke

Reputation: 5060

EDIT: 'sync' is triggered on the model after it is removed from the collection, even if wait:true option is used.

Here is the code from Backbone, which triggers the model events on the collection.

// 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.
_onModelEvent: function(event, model, collection, options) {
  if ((event === 'add' || event === 'remove') && collection !== this) return;
  if (event === 'destroy') this.remove(model, options);
  if (model && event === 'change:' + model.idAttribute) {
    delete this._byId[model.previous(model.idAttribute)];
    if (model.id != null) this._byId[model.id] = model;
  }
  this.trigger.apply(this, arguments);
},

Your problem is most likely because the 'sync' event is not triggered on the model (and then triggered on the collection) due to an error in during the sync.

From the Backbone source, you can see that 'sync' is triggered when the request succeeds, so maybe you can debug that and see if the success callback in sync is hit?

var success = options.success;
    options.success = function(resp) {
      if (success) success(model, resp, options);
      model.trigger('sync', model, resp, options);  // breakpoint here.
    };

Can you put a breakpoint in there and see if the event is triggered? I assume it will not hit this line.

Also try using an error callback:

myCollection.at(0).destroy({
    error: function(model, xhr, options){
        console.log(model);  // this will probably get hit
    }
});

Upvotes: 4

Related Questions