I have two backbone models, loaded from server:
var Model = Backbone.Model.extend({});
var SubModel = Backbone.Model.extend({});
var SubCollection = Backbone.Collection.extend({
model: SubModel
});
var m = new Model();
m.fetch({success: function(model)
{
model.submodels = new SubCollection();
model.submodels.url = "/sub/" + model.get("id");
model.submodels.fetch();
}});
So, the server has to send two separate responses. For example:
{ name: "Model1", id: 1 } // For Model fetch
and
[{ name: "Submodel1", id: 1 }, { name: "Submodel2", id: 2 }] // For Submodel collection fetch
Is there a way to fetch a Model instance with Submodel collection at once, like:
{
name: "Model1",
id: 1,
submodels: [{ name: "Submodel1", id: 2 }, { name: "Submodel1", id: 2 }]
}
To be able to do that is up to your back-end - it doesn't really have anything to do with Backbone.
Can you configure your back-end technology to return related models as nested resources?
If your back-end is Rails, for instance, and your models are related in ActiveRecord, one way of doing this is something like
respond_to do |format|
format.json { render :json => @model.to_json(:include => [:submodels])}
end
What back-end technology are you using?
Edit:
Sorry, misunderstood the gist of your question, once you've got your back-end returning the JSON in the proper format, yeah, there are things you need to do in Backbone to be able to handle it.
Backbone-Relational
One way to deal with it is to use Backbone-Relational, a plugin for handling related models.
You define related models through a 'relations' property:
SubModel = Backbone.RelationalModel.extend({});
SubCollection = Backbone.Collection.extend({
model: SubModel
});
Model = Backbone.RelationalModel.extend({
relations: [
{
type: 'HasMany',
key: 'submodels',
relatedModel: 'SubModel',
collectionType: 'SubCollection'
}
]
});
When your Model fetches the JSON, it will automatically create a SubCollection under the 'submodels' property and populate it with SubModels - one for each JSON object in the array.
jsfiddle for backbone-relational: http://jsfiddle.net/4Zx5X/12/
By Hand
You can do this by hand if you want as well. In involves overriding the parse function for your Model class (forgive me if my JS is not 100% correct - been doing CoffeeScript so much lately its hardwired in my brain)
var Model = Backbone.Model.extend({
parse: function(response) {
this.submodels = new SubCollection();
// Populate your submodels with the data from the response.
// Could also use .add() if you wanted events for each one.
this.submodels.reset(response.submodels);
// now that we've handled that data, delete it
delete response.submodels;
// return the rest of the data to be handled by Backbone normally.
return response;
}
});
parse() runs before initialize() and before the attributes hash is set up, so you can't access model.attributes, and model.set() fails, so we have to set the collection as a direct property of the model, and not as a "property" that you would access with get/set.
Depending on what you want to happen on "save()" you may have to override `toJSON' to get your serialized version of the model to look like what your API expects.
jsfiddle:
http://jsfiddle.net/QEdmB/44/
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