"How" to save an entire collection in Backbone.js - Backbone.sync or jQuery.ajax?

Viewed 47898

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" is it written in code? (the post explains it in English. It'd be great to have a javascript specific explanation :)

Say I have a collection of models - the models themselves may have nested collections. I have overridden the toJSON() method of the parent collection and I am getting a valid JSON object. I wish to "save" the entire collection (corresponding JSON), but backbone doesn't seem to come in-built with that functionality.

var MyCollection = Backbone.Collection.extend({
model:MyModel,

//something to save?
save: function() {
   //what to write here?
 }

});

I know somewhere you have to say:

Backbone.sync = function(method, model, options){
/*
 * What goes in here?? If at all anything needs to be done?
 * Where to declare this in the program? And how is it called?
 */
}

Once the 'view' is done with the processing it is responsible for telling the collection to "save" itself on the server (capable of handling a bulk update/create request).

Questions that arise:

  1. How/what to write in code to "wire it all together"?
  2. What is the 'right' location of the callbacks and how to specify a "success/error" callback? I mean syntactically?I'm not clear of the syntax of registering callbacks in backbone...

If it is indeed a tricky job then can we call jQuery.ajax within a view and pass the this.successMethod or this.errorMethod as success/error callbacks?? Will it work?

I need to get in sync with backbone's way of thinking - I know I'm definitely missing something w.r.t., syncing of entire collections.

11 Answers

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').

Related