I've got the following model with nested collection
var Mdl = Backbone.Model.extend({
initialize: function() {
// collection
this.col1 = new NestedCollection();
},
...
});
I would like to send the data for both the model and the models in the collection in one request looking something like:
{
att1: val,
col1: [{obj1: val}, {...}]
}
I'm unsure about the best way to hand the data in the request to the nested collection (col1). I can't do ...
var Mdl = Backbone.Model.extend({
initialize: function() {
// collection
this.col1 = new NestedCollection(this.get('col1');
},
...
});
... because at the time of initialize is called the parse function of the model has not been called which means that the attribute col1 is empty, another solution I thought of was to listen for the change in the parent model like...
model.bind("change:tags", function() {
model.col1.refresh(model.get('col1'));
});
however this solution feels a little heavy handed and might potentially break any
this.col1.bind("add", function() {})
and
this.col1.bind("remove", function() {})
function set-up on the collection.
Has anyone got any idea of the 'official' way of doing this?
Thanks.
The "official" way is to override the parse method:
http://documentcloud.github.com/backbone/#Model-parse
In your specific case, what I would probably do is, in the parse method, build the nested collection from the col1 data, delete it from the results, then hand the results on. Backbone will then turn the rest of the data into properties.
I have not tried this, so I'm not 100% sure it works:
parse: function(response) {
this.col1 = new NestedCollection(response.col1);
delete response.col1
return response
}
Edit: Nov 28th 2012
Harm points out that this might not be the best way to do it any more. The original answer was written quite a while ago, and the original question indicated that the user wanted the collection to be a property on the model (not an attribute), but Harm has a point that having the collection as an attribute is a more accepted way of doing it these days.
Today, you could use something like Backbone-Relational to handle a lot of this stuff for you, or, if you wanted to do it yourself, and have the collection as a model attribute, you could do something like:
Building = Backbone.Model.extend({
parse: function(response) {
console.log("Parse Called");
response.rooms = new Rooms(response.rooms);
return response;
}
});
Room = Backbone.Model.extend({});
Rooms = Backbone.Collection.extend({
model: Room
});
science_building = new Building();
science_building.fetch(
{success: function(model,resp) {console.log(resp);}}
);
With a model fetch response like:
{ id: 1,
name: "Einstein Hall",
rooms: [
{id:101, name:'Chem Lab'},
{id:201, name:'Physics Lab'},
{id:205, name:'Bio Lab'}
]
}
Resulting in a Building model that allows:
science_building.get('rooms').get(101).get('name') // ==> "Chem Lab"
A working jsFiddle example: http://jsfiddle.net/edwardmsmith/9bksp/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With