I'm trying to build an order system for a friend using django/tastypie on the server side and backbone/marionette on the client side. The server side poses no bigger problem but since I'm an inexperienced frontend developer I'm kinda stuck;
The simpler case went just fine, e.g. to list, add, edit and remove an Article (just a table in my database with sku, description and so on) using Composite- and ItemViews.The problem is when I'm trying to construct the views for an Order since it consists of several tables with relations on the server side.
Order
LineItem
Article
StoreQuantity
Store
StoreQuantity
Store
LineItem
Article
StoreQuantity
Store
StoreQuantity
Store
...
So an Order consists of several LineItems. A LineItem consists of an Article and several StoreQuantity:s making it possible to model something like "Order Article A; 10 copies to Store X and 4 copies to Store Y, Article B; 4 copies to Store X and 1 copy to Store Y".
I guess my question is; how would I go about to construct my views for something like above?
Would something like below be the wrong way?
Create an OrderCompositeView and pass it the OrderModel from my controller.
When OrderModel is fetched from the server, let OrderCompositeView create a LineItemCompositeView.
When LineItemCompositeView has fetched its' LineItemCollection from the server.. and so on recursively
Should I create a REST-url that returns the entire JSON for an Order and its relations instead of several smaller recursive calls, and then try to parse the JSON client side?
I've found several good resources on how to get going with Marionette but none on how to handle data nested several layers deep.
Thanks /Magnus
Edit:
Showing some code illustrating what I've been testing
(Views)
var LineItemDetailView = Backbone.Marionette.ItemView.extend({
template: "#lineitem-layout-template",
tagName: "div",
initialize: function() {
}
});
var LineItemView = Backbone.Marionette.CompositeView.extend({
template: "#lineitem-wrapper-template",
childView: LineItemDetailView,
childViewContainer: "div",
initialize: function(coll, obj) {
this.collection = new LineItemCollection({url: "api/v1/lineitem/?order__id=" + obj["order_id"]});
this.collection.fetch({
success: function() {
console.log("Successfully fetched lineitems");
}
});
}
});
var OrderDetailView = Backbone.Marionette.CompositeView.extend({
template: "#order-detail-template",
childView: LineItemView,
childViewContainer: "#lineitems",
initialize: function() {
this.model.on("sync", function(mod) {
lineitemView = new LineItemView([],{order_id: mod.get("id")});
});
}
});
Something along those lines. OrderDetailView is created from my controller and passed the OrderModel. I from this I get OrderDetailView:s template to render and the LineItemCollection is fetched from server but nothing more happens.
So I ran into this when creating a survey portion of an app the other day. It had a structure like this: Survey: Question: Answer Answer Question: Answer Answer
So pretty similar to what you're doing. I used the backbone-relational gem - http://backbonerelational.org/ to relate the models together and it worked great. My API sends back all of the JSON in a single call. So surveys/1.json brings back all of the above pieces/their data. Then I parse/break them up with Backbone relational. Here's what they look like:
Survey:
Question:
Answer:
Then when you go to display them, in my survey display view I have a layout view that has a question region which uses a composite view of the survey questions like this:
Then I come in and get the questions:
The childview of the Questions CompositeView is itself a CompositeView with a childview of answers.
So Survey has a Questions CompositeView of Questions, each of which is a CompositeView of Answers.
You should be able to follow a similar structure with your app. Let me know if you get stuck anywhere!
Edit: Adding View/Controllers.
So here's what I do, when the user navigates to a certain route - say localhost:3000/#surveys/1/edit it hits my surveysrouter (note some code like the list piece I stripped out):
So I can get here when navigating or by triggering the "survey:clicked" event. This then creates my show controller:
This makes a new Questions Show Controller (same router case as above that handles
"show:survey:questions"
request and instigates a new controller so I'll skip that code).Standard composite view for the questions:
Then each question is a composite view:
It gets its collection from the answers group from backbone relational. I would note though that this probably should just be a layout and in the initialize function I should send a request to the answers app to get a list of answers and add those to the answer region. I just haven't gotten around to that yet :).