I have a model which links to two sub-models like so:
var SubModel = Backbone.Model.extend({
defaults: {
headline: null,
image_url: null,
url: null
}
});
var MainModel = Backbone.Model.extend({
defaults: {
subModelA: null,
subModelB: null,
title: null
},
urlRoot: function() {
if (this.isNew()) {
return '/mainmodel/new';
}
return '/mainmodel';
},
initialize: function() {
this.fetch();
},
parse: function(data) {
var response = {};
response.subModelA = new SubModel(data.subModelA);
response.subModelB = new SubModel(data.subModelB);
response.title = data.title;
return response;
}
});
The issue I'm currently having is that calling var mainModelInstance = new MainModel() does correctly fetch from /mainmodel/new but mainModelInstance.attributes is always a blank object {}.
var mainModelInstance = new MainModel();
mainModelInstance.attributes; // Returns {}
Here is a sample of the server's response to /mainmodel/new:
{
"title": "Politics",
"subModelA": {
"headline": "Investigators: Iran tried to smuggle suicide belts, missiles by boat into Yemen",
"url": "http://dailycaller.com/2013/02/09/yemen-minister-says-weapons-came-from-iran/",
"image_url": "http://cdn01.dailycaller.com/wp-content/uploads/2013/02/54c7d52e1a384db489ab9ea568afddb0-e1360455589316.jpg"
},
"subModelB": {
"headline": "Review: Who needs Windows RT? Acer's Iconia W510 runs the real thing",
"url": "http://arstechnica.com/gadgets/2013/02/review-who-needs-windows-rt-acers-iconia-w510-runs-the-real-thing/",
"image_url": "http://cdn.arstechnica.net/wp-content/uploads/2013/02/w510-main-640x388.jpg"
}
}
It seems as though the model's attributes are not being updated via parse. Why aren't the model's attributes being updated?
Your code might as well be working, but you are not testing it correctly
You are calling this.fetch in yout initialize method.
calling model.fetch is an asynchronous call and when you are trying to evaluate mainModelInstance.attributes, the http request call is not yet completed.
You should test this with:
var mainModelInstance = new MainModel();
mainModelInstance.on('change', function() {
console.log(mainModelInstance.toJSON());
});
or even better, dont auto fetch on initialize (its not a best practice anyway)
and use the jQuery promise pattern:
var mainModelInstance = new MainModel();
mainModelInstance.fetch().done(function () {
console.log(mainModelInstance.toJSON());
});
This is just a work in progress answer, feel free to discuss in the comments.
I would change your MainModel definition like so:
subModelA: new SubModelA(),
subModelB: new SubModelB(),
parse: function(data){
this.subModelA.set(data.subModelA);
this.subModelB.set(data.subModelB);
return data; // we keep two copies of the data, in mainModel and submodels.
}
So assuming your server responds exactly like in your answer
var model = new MainModel();
model.get('title'); // Politics
model.subModelA.get('headline'); // Investigators: Iran tr...
Then, you may have to override the save method depending on how you wish to persist things back to the server — this might work.
save: function(key, val, options) {
this.set({
subModelA: this.subModelA.toJSON(),
subModelB: this.subModelB.toJSON()
});
Backbone.Model.prototype.save.apply(this, arguments);
}
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