Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone - Collections nested in Models

Tags:

Is it possible to nest collections within models?

I know that you can create new collections in the initialize callback of a model, and create references that you can pass back and forth between the collection and parent model. But is it possible to set the collection as part of the model, such that the JSON it exports looks like this:

{   blah: 'blah',   myCollection: [       {          foo: 'asdf',          bar: 'qwer'       },       {          foo: 'asdf123',          bar: 'qwer123'       }   ] } 

If not, how do you handle syncing a model with related collections to the backend? Do you have to tap into backbone's sync and rebuild the JSON or is there something more seamless?

Sorry if this question has been answered elsewhere. I've looked around and seen some workarounds, but nothing that really answers what I'm looking for.

like image 788
Jon Raasch Avatar asked Sep 02 '11 19:09

Jon Raasch


2 Answers

There are two approaches. The first is to define a root Model that gets everything. You override it's parse() method to create sub-collections and sub-models for nested attributes, and override the toJSON() method to convert back to the JSON structure, suitable for saving to the server.

This is perfectly acceptable for small subcollections. It takes a bit of programming, but if you can read the Backbone source code, how to do it should be, well, not obvious, but at least understandable.

Or you can use Backbone Relational, which does all the work for you.

like image 92
Elf Sternberg Avatar answered Sep 20 '22 22:09

Elf Sternberg


Renato was close but "has" and "set" will not be available yet. I believe Reckoner pointed out part of that. Also, you will need to delete the property from the response, else it will override the default value.

_.extend(Backbone.Model.prototype, {     parse: function(resp, xhr) {         var attr, model, models, collection, options;         for (var prop in resp) {             if (this.defaults && this.defaults[prop]) {                 attr = this.defaults[prop];                 if (attr instanceof Backbone.Model) {                     model = attr.clone();                     model.set(resp[prop]);                     resp[prop] = model;                 } else if (attr instanceof Backbone.Collection) {                     models = attr.map(function (model) { return model.clone(); });                     options = _.clone(attr.options);                     collection = new attr.constructor(models, options);                     collection.add(resp[prop]);                     resp[prop] = collection;                 }             }         }         return resp;     } }); 

Hope that helps someone.

like image 21
Brian Lewis Avatar answered Sep 21 '22 22:09

Brian Lewis