I am well aware it can be done and I\'ve looked at quite a few places (including: Best practice for saving an entire collection?). But I\'m still not clear \"exactly how\"
For anyone who is still using backbone.js in 2017, the accepted answer is not working.
Try removing the toJSON() override in the wrapper model and calling toJSON on the collection when you instantiate the model wrapper.
new ModelWrapper(Collection.toJSON());
This really depends on what the contract is between the client and server. Here's a simplified CoffeeScript example where a PUT to /parent/:parent_id/children
with {"children":[{child1},{child2}]}
will replace a parent's children with what's in the PUT and return {"children":[{child1},{child2}]}
:
class ChildElementCollection extends Backbone.Collection
model: Backbone.Model
initialize: ->
@bind 'add', (model) -> model.set('parent_id', @parent.id)
url: -> "#{@parent.url()}/children" # let's say that @parent.url() == '/parent/1'
save: ->
response = Backbone.sync('update', @, url: @url(), contentType: 'application/json', data: JSON.stringify(children: @toJSON()))
response.done (models) => @reset models.children
return response
This is a pretty simple example, you can do a lot more... it really depends on what state your data's in when save() is executed, what state it needs to be in to ship to the server, and what the server gives back.
If your server is ok with a PUT of [{child1},{child2]
, then your Backbone.sync line could change to response = Backbone.sync('update', @toJSON(), url: @url(), contentType: 'application/json')
.
I would try something like:
var CollectionSync = function(method, model, [options]) {
// do similar things to Backbone.sync
}
var MyCollection = Backbone.Collection.extend({
sync: CollectionSync,
model: MyModel,
getChanged: function() {
// return a list of models that have changed by checking hasChanged()
},
save: function(attributes, options) {
// do similar things as Model.save
}
});
( https://stackoverflow.com/a/11085198/137067 )
I was also surprised that Backbone collections don't have a built in save. Here's what I put on my backbone collection to do it. I definitely don't want to iterate through each model in the collection and save independently. Also, I am using Backbone on the backend using Node so am overridding the native Backbone.sync
to save to a flat file on my small project—but the code should pretty much be the same:
save: function(){
Backbone.sync('save', this, {
success: function(){
console.log('users saved!');
}
});
}
I ended up just having a 'save' like method and called $.ajax within it. It gave me more control over it without the need to add a wrapper class as @brandgonesurfing suggested (although I absolutely love the idea :) As mentioned since I already had the collection.toJSON() method overridden all I landed up doing was using it in the ajax call...
Hope this helps someone who stumbles upon it...