为嵌套多个级别的数据构造视图 [英] Construct views for data nested several levels deep

查看:92
本文介绍了为嵌套多个级别的数据构造视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用服务器端的django/tastypie和客户端端的骨干/木偶为朋友构建订单系统.服务器端不会带来更大的问题,但是由于我是一个没有经验的前端开发人员,所以我有点被卡住了;

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;

最简单的情况很好,例如列出,添加,编辑和删除使用Composite-和ItemViews的Article(只是我的数据库中具有sku,description等的表)的问题是当我试图为Order构建视图时,因为它由服务器端具有关系的几个表.

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.

订购
   LineItem
   Article
   StoreQuantity
      Store
   StoreQuantity
      Store

Order
  LineItem
   Article
   StoreQuantity
      Store
   StoreQuantity
      Store

  LineItem
   Article
   StoreQuantity
      Store
   StoreQuantity
      Store

...

  LineItem
   Article
   StoreQuantity
      Store
   StoreQuantity
      Store

...

因此,订单由几个LineItem组成.一个LineItem由一个Article和几个StoreQuantity组成:可以对订购商品A;对X商店10份副本,对Y商店B,4份副本;对X商店4份副本和对Y商店1份副本"进行建模

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?

  • 创建一个OrderCompositeView并将其从我的控制器传递给OrderModel.

  • Create an OrderCompositeView and pass it the OrderModel from my controller.

从服务器获取OrderModel时,让OrderCompositeView创建LineItemCompositeView.

When OrderModel is fetched from the server, let OrderCompositeView create a LineItemCompositeView.

当LineItemCompositeView从服务器获取其LineItemCollection时,等等.递归

When LineItemCompositeView has fetched its' LineItemCollection from the server.. and so on recursively

我是否应该创建一个REST-url来返回Order及其关系的整个JSON,而不是几个较小的递归调用,然后尝试解析JSON客户端?

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?

我已经找到了一些很好的资源来了解如何使用Marionette,但没有找到如何处理嵌套在多层中的数据.

I've found several good resources on how to get going with Marionette but none on how to handle data nested several layers deep.

感谢/Magnus

显示一些说明我正在测试的代码

Showing some code illustrating what I've been testing

(观看次数)

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")});
        });
    }
});

遵循这些原则. OrderDetailView是从我的控制器创建的,并传递了OrderModel.我从中得到要渲染的OrderDetailView:s模板,并且从服务器获取了LineItemCollection,但是什么也没有发生.

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

与您正在做的事情非常相似.我使用了骨干关系型宝石- http://backbonerelational.org/将模型关联在一起,并且效果很好.我的API在一次调用中发送回了所有JSON.因此surveys/1.json会带回上述所有片段/它们的数据.然后,我使用Backbone关系解析/分解它们.它们是这样的:

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:

调查:

class Entities.Survey extends App.Entities.Model
    urlRoot: "surveys"

    defaults: 
      status: "Draft"
      number_taken: 0
      survey_limit: 500

    relations: [
      type: Backbone.HasMany
      key: "questions"
      relatedModel: Entities.Question
      reverseRelation: 
        key: 'survey'
        includeInJSON: 'id'
    ]

问题:

class Entities.Question extends App.Entities.Model
    urlRoot: "questions"

    defaults:
      single_response: true
      terminate: false
      free_text: false

    relations: [
      type: Backbone.HasMany
      key: "answers"
      relatedModel: Entities.Answer
      reverseRelation: 
        key: 'question'
        includeInJSON: 'id'
    ]

答案:

class Entities.Answer extends App.Entities.Model
    urlRoot: "answers"

    defaults:
      branching: false
      next_question_id: null

然后,当您要显示它们时,在我的调查显示视图中,我有一个布局视图,其中包含一个问题区域,该区域使用类似以下调查问题的组合视图:

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:

class Show.Controller extends App.Controllers.Application

    initialize: (options) ->
      { survey, id } = options
      survey or= App.request "survey:entity", id

      App.execute "when:fetched", survey, =>
        @layout = @getLayoutView()

        @listenTo @layout, "show", =>
          @panelRegion survey
          @questionRegion survey
          @bannerRegion survey

        @show @layout

    questionRegion: (survey) ->
      App.request "show:survey:questions", survey, @layout.questionRegion

然后我进来回答问题:

questionRegion: (survey) ->
      questions = survey.get('questions')
      questionView = @getQuestionView questions, survey

问题CompositeView的子视图本身就是具有答案子视图的CompositeView.

The childview of the Questions CompositeView is itself a CompositeView with a childview of answers.

所以Survey有一个Questions的Questions CompositeView,每个问题都是一个Composites 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!

添加视图/控制器.

这就是我的工作,当用户导航到某条路线时,例如localhost:3000/#surveys/1/edit,它击中了我的surveysrouter(请注意一些代码,例如我剥离的清单):

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):

@TheoremReach.module "SurveysApp", (SurveysApp, App, Backbone, Marionette, $, _) ->

  class SurveysApp.Router extends Marionette.AppRouter
    appRoutes:
      "surveys"             : "list"
      "surveys/:id"         : "show"
      "surveys/:id/take": "take"

  API =
    show: (id, survey) ->
        new SurveysApp.Show.Controller
            id: id
            survey: survey

    take: (id, survey) ->
      new SurveysApp.Take.Controller 
        id: id 
        survey: survey

  App.vent.on "survey:clicked", (survey) ->
    App.navigate "surveys/" + survey.id
    API.show survey.id, survey

  App.vent.on "take:survey:button:clicked", (survey) ->
    App.navigate "surveys/" + survey.id + "/take"
    API.take survey.id, survey

  App.addInitializer ->
    new SurveysApp.Router
      controller: API

因此,我可以在导航或触发"survey:clicked"事件时到达此处.然后创建我的显示控制器:

So I can get here when navigating or by triggering the "survey:clicked" event. This then creates my show controller:

@TheoremReach.module "SurveysApp.Show", (Show, App, Backbone, Marionette, $, _) ->

  class Show.Controller extends App.Controllers.Application

    initialize: (options) ->
      { survey, id } = options
      survey or= App.request "survey:entity", id

      App.execute "when:fetched", survey, =>
        @layout = @getLayoutView()

        @listenTo @layout, "show", =>
          @panelRegion survey
          @questionRegion survey
          @bannerRegion survey

        @show @layout

    questionRegion: (survey) ->
      App.request "show:survey:questions", survey, @layout.questionRegion

    panelRegion: (survey) ->
      panelView = @getPanelView survey

      @listenTo panelView, "new:question:clicked", (args) ->
        question = App.request "new:question:entity"
        model = args.model
        model.get('questions').add(question)
        question.set(survey_id: model.get('id'))
        App.request "new:question:added"

      @show panelView, region: @layout.panelRegion

    bannerRegion: (survey) ->
      bannerView = @getBannerView survey

      @listenTo bannerView, "take:survey:button:clicked", (args) ->
        App.vent.trigger "take:survey:button:clicked", args.model

      @show bannerView, region: @layout.bannerRegion

    getLayoutView: ->
      new Show.Layout

    getBannerView: (survey) ->
      new Show.Banner
        model: survey

    getPanelView: (survey) ->
      new Show.Panel
        model: survey

这将创建一个新的问题显示控制器"(与上述路由器情况相同,可以处理"show:survey:questions"请求并启动一个新控制器,因此我将跳过该代码).

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).

@TheoremReach.module "QuestionsApp.Show", (Show, App, Backbone, Marionette, $, _) ->

  class Show.Controller extends App.Controllers.Application

    initialize: (options) ->
      { survey } = options
      @layout = @getLayoutView()

      @listenTo @layout, "show", =>
        @questionRegion survey

      @show @layout

    questionRegion: (survey) ->
      questions = survey.get('questions')
      questionView = @getQuestionView questions, survey

      App.reqres.setHandler "new:question:added", ->
        questionView.render()

      @show questionView, region: @layout.questionRegion

    getLayoutView: ->
      new Show.Layout

    getQuestionView: (questions, survey) ->
      new Show.Questions
        collection: questions
        model: survey

问题的标准组合视图:

class Show.Questions extends App.Views.CompositeView
    template: "questions/show/_questions"
    className: "questions"
    itemViewContainer: ".editor"
    itemView: Show.Question 

然后每个问题都是一个复合视图:

Then each question is a composite view:

class Show.Question extends App.Views.CompositeView
    template: "questions/show/_question"
    id: "1000"
    className: "step"
    initialize: ->
      @collection = @model.get("answers")
      @model.set(question_number: @model.collection.indexOf(@model) + 1)
      if @model.get('free_text') and @model.get('answers').length < 1
        answer = App.request "new:answer:entity"
        answer.set(free_text: true, question: @model, title: @model.get('title'))
        @collection.reset(answer, {silent: true})
      @on "childview:answer:delete:clicked", (child, args) =>
        args.collection = @model.get('answers')
        @trigger "answer:delete:clicked", args

    itemView: Show.Answer 
    itemViewContainer: ".answer-container"

它从骨干关系的答案组中获取其集合.我要指出的是,这可能应该只是一个布局,在initialize函数中,我应该将一个请求发送到Answers应用程序,以获取答案列表并将其添加到答案区域.我只是还没有解决这个问题:).

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 :).

这篇关于为嵌套多个级别的数据构造视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆