1
votes

I would like to be able to call save() on a backbone model and have the backend return the entire collection of this model instead of only the changed attributes of the model. I would then like backbone to update the entire returned collection. The use case for this is the following:

A user has multiple addresses and can choose a shipping address from this collection. If she chooses a different shipping address from the collection the previous shipping address should be updated to the state of 'just another plain address'. For this the entire collection has to be updated instead of only the changed model.

Is this somehow possible in backbone.js?

Thanks a lot in advance!

4

4 Answers

4
votes

models that are bound to collections, contain their collection parent as a property. Also, since your returning a list of models, we can assume that it is always in a list.

mymodel = Backbone.Model.extend({
   parse: function (data) {
     if(this.collection && typeof(data) === 'array') {
        this.collection.reset(data);
     }
     return data;
   }
});
2
votes

I do not think that overriding sync or breaking the expectations of what save returns is necessary here.

It would be simpler I guess to override save on the model, something on the lines of:

save: function (key, value, options) {
    var p = Model.prototype.save.call(this, key, value, options),
        self=this;
    if (this.collection) {
        p.done(function () { self.collection.fetch(); });
    }
    return p;
}

which will save using the normal save obtaining its promise, and then if saving was successful and the model is part of a collection, it will fetch the collection from the server.

Another way would be to bind to the model's change event, check if it belongs to a collection and fetch, but that would also happen on set.

1
votes

Yep, it's possible. You'll need to override the sync function on the model

MyModel = Backbone.Model.extend({
  sync: function(method, model) {
    if (method === 'create') {
      //perform save logic and update the model's collection
    } else if (method === 'update') {
      //perform save logic and update the model's collection
    } else if (method === 'read') {
      ...
    } else if (method === 'destroy') {
      ...
    }
  }
});

Take a look at the Backbone.sync function for more information.

0
votes

What your use case actually calls for is the updating of two models, not the updating of an entire collection. (Other than fetching, collections don't interact with the server in Backbone.) Assuming you have addresses A, B, and C, with A as the current shipping address and C as the new shipping address, your code can simply:

  1. Update C to be the new shipping address.
  2. Update A to be 'just another address.'

If your problem is that you don't know which address is the current address (i.e., address A), then you can just search inside your collection for it (i.e., "give me the current shipping address"), update C, and then update the returned address (address A).

If you absolutely need to update an entire collection (you don't), cycle through collection.models and update each one individually. There simply is no concept in Backbone of a collection being acted upon RESTfully.

Edit: I may have misread your question. If you meant update the collection on the client (i.e., you didn't intend to update the collection on the server), then the code is still similar, you just update both the old model and the new one.