mardi 3 février 2015

How can I fetch() related models in parse() with Backbone.js?


Consider we are working with an API that exposes two objects, Parent and Child, where a Parent has many Child objects. The server represents this relationship in representations of Parent objects as a list of IDs of Child objects:



{
...
children: [1, 2, 5, 19, ...],
...
}


Assuming we can't change the server's response, how can we fetch Child objects when fetching Parents object using Backbone.js? Roughly, the following code is what I want, but it does not work because child.fetch() is asynchronous:



var Child = Backbone.Model.extend({
url: function() {
return "/children/" + this.model.get('id');
}
});

var Parent = Backbone.Model.extend({
parse: function(response) {
response.children = _.map(response.children, function(id) {
var child = Child({id: id});
child.fetch(); // Ideally, this would be synchronous
return child.attributes;
});
return response;
},
url: function() {
return "/parents/" + this.model.get('id');
}
});

var parent = new Parent({id: 0});
Parent.fetch();


Without this piece, I cannot render my views, which has Child views nested within Parent views:



var ParentView = Backbone.View.extend({
initialize: function() {
this.childViews = _.map(this.model.get('children'), function(child) {
return ChildView({model: child});
});
},

template: _.template($('#parent-template').html()),

render: function() {
this.$el.html(this.template(this.model.toJSON()));
_.each(this.childViews, function(view) {
this.$el.append(view.render().el);
});
return this;
}
});

var ChildView = Backbone.View.extend({
template: _.template($('#parent-template').html()),

render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});


Several solutions have occurred to me so far, but none of them work without drawbacks:




  • Move the fetch() logic into initialize(), but this runs into all the same problems, plus leaving the model in an inconsistent state between fetch() and initialize().




  • fetch() (and render()) the Child objects in Parent.render(), but this contaminates rendering with initialization logic.







Aucun commentaire:

Enregistrer un commentaire