Wie in Backbone beschrieben ( http://backbonejs.org/#FAQ-nested ) sollten Sie die folgende Methode verwenden...
Edit: Sie benötigen keine Plugins. Außerdem empfehle ich dies nicht, da man bei Backbone sicher sein kann, dass man ein grundsolides Framework hat, aber sie überprüfen nicht, wie grundsolide jedes Plugin ist, das sie auf ihrer Website verbreiten. Ich hatte viele Projekte, bei denen ich über Verschachtelung nachdenken musste. Am Ende war der hier gezeigte Weg der sicherste und konventionellste.
Strucutre
var Order = Backbone.Model.extend({
initialize : function(data) {
this.orderItems = new OrderItems(null, {order:this});
if (!!data.order_items) {
this.orderItems.reset(data.order_items, {parse:true});
//we dont want nesting in "attributes"
this.unset("order_items");
}
},
// this is used, when a change from server happens. So when
// the model already exists, and the stuff in initialize
// wouldnt be called anymore.
parse : function(data) {
if (!!data.order_items) {
this.orderItems.reset(data.order_items);
delete data.order_items;
}
return data;
}
});
var Orders = Backbone.Collection.extend({
model : Order
});
var OrderItem = Backbone.Model.extend({
});
var OrderItems = Backbone.Collection.extend({
model : OrderItem,
initialize : function(data, options) {
if (options && options.order) {
this.order = options.order;
}
}
};
Verbindlich
myOrder.orderItems.on("...");
myOrder.on("...");
Zugang
Zugriff auf Ihre Bestellung aus den OrderItems heraus.
var someOrderItem = myOrders.get(1).orderItems.first();
someOrderItem.collection.order === myOrders.get(1)
// will result in "true"
Langsames Laden
Manchmal wollen wir nicht alles in einer einzigen Anfrage laden. Meistens ziehe ich es vor, die Basissammlung zu laden, und nur wenn eine Ansicht ein Modell lädt und das Modell Untersammlungen hat, rufe ich sie später ab. Hierfür habe ich eine fetchOnce-Methode.
var OrderItems = Backbone.Model.extend({
initialize : function() {
if (options && options.order) {
this.order = options.order;
}
this.fetchOnce = _.once(this.fetch, this);
//this will always return you an jquery xhr deferred.
},
url : function() {
if (this.order) {
// url() would return you something like "/order/1234"
return this.order.url() + "/items"
}
}
);
An anderer Stelle würden Sie dann Ihre kompletten Aufträge initialisieren und abrufen.
var orders = new Orders();
orders.fetch();
Wenn Sie dann eine Bearbeitungsansicht aufrufen und möchten, dass auch alle Auftragspositionen angezeigt werden, müssen Sie Folgendes tun.
var view = new Backbone.View({
order : orders.get(1)
});
view.order.orderItems.fetchOnce().done(function() {
view.render();
});
da fetchOnce ein neues Deferred zurückgibt, wenn es nicht vorhanden ist, oder ein vorhandenes (wegen _.once) können Sie immer an es binden, wenn es bereits zuvor aufgerufen wurde, werden Sie in der done auch benachrichtigt werden...