Marionette在CompositeView事件触发/冒泡中嵌套CompositeView

时间:2014-08-03 22:21:42

标签: javascript backbone.js marionette

我正在创建一个基本的调查应用程序来学习木偶/掌握嵌套模型(答案>问题>调查)。我正在使用骨干关系来实现这一目标。

在调查视图中,我使用复合视图来倾听每个问题。每个问题也是一个复合视图,循环遍历每个问题的答案。这一切都有效。我无法弄清楚如何访问/冒泡回答ItemViews中发生的事件并质疑CompositeView。知道我应该怎么做吗?

通常,当我只使用一个CompositeView时,我可以在视图中使用这个:

triggers:
   "click a.delete": "delete:clicked"

然后在控制器中

@listenTo view, "childview:delete:clicked", ->
  console.log "delete clicked"

但这种模式似乎对我目前的结构不起作用。当点击删除按钮时,我还尝试了触发事件的路线>手动触发事件,但除了正确记录到控制台之外,这不起作用。

我出错的任何想法?非常感谢任何帮助!

控制器:

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

  class List.Controller extends App.Controllers.Application

    initialize: ->
      survey = App.request "survey:entity", 1

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

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

        @show @layout

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

      @listenTo questionView, "answer:delete:clicked", (child, args) ->
        console.log "answer deleted!"
        # model = args.model 
        # if confirm "Are you sure you want to delete #{model.get("title")}?" then model.destroy() else false

      @listenTo questionView, "childview:question:delete:clicked", (child, args) ->
        console.log "question deleted!"
        # model = args.model 
        # if confirm "Are you sure you want to delete #{model.get("title")}?" then model.destroy() else false

      @show questionView, region: @layout.questionRegion

    panelRegion: ->
      panelView = @getPanelView()
      @show panelView, region: @layout.panelRegion

    bannerRegion: (survey) ->
      bannerView = @getBannerView survey
      @show bannerView, region: @layout.bannerRegion

    getLayoutView: ->
      new List.Layout

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

    getPanelView: ->
      new List.Panel

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

查看:

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

  class List.Layout extends App.Views.Layout
    template: "surveys/list/list_layout"

    regions: 
      questionRegion: "#question-region"
      newRegion: "#new-region"
      panelRegion: "#panel-region"
      bannerRegion: "#banner-region"

  class List.Answer extends App.Views.ItemView
    template: "surveys/list/_answer"
    className: "answer-container"

    events:
      "click a.delete-button": "deleteAnswer"

    deleteAnswer: (e) ->
      e.preventDefault()
      @trigger "answer:delete:clicked", @model
      console.log "deleteAnswer"

  class List.Question extends App.Views.CompositeView
    template: "surveys/list/_question"
    id: "1000"
    className: "step"
    initialize: ->
      @collection = @model.get("answers")

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

    triggers:
      "click .delete-question-button": "quesiton:delete:clicked"

  class List.Questions extends App.Views.CompositeView
    template: "surveys/list/_questions"
    className: "questions"
    itemViewContainer: ".editor"
    itemView: List.Question 

  class List.Banner extends App.Views.ItemView
    template: "surveys/list/_banner"
    id: "survey-builder"
    className: "my-fluid-container"

  class List.Panel extends App.Views.ItemView
    template: "surveys/list/_panel"
    id: "add-question"

编辑:添加HTML

布局视图:

<div id="banner-region"></div>

<div class="container">
    <div id="question-region"></div>
    <div id="panel-region"></div>
    <div id="new-region"></div>
</div>

横幅视图:

<div class="container">
    <a id="back" href="#">
      <i class="fa fa-chevron-left"></i></span>
    </a>
    <div class="message"><%= @title %></div>
    <div class="btn btn-inline pull-right checkout">Checkout</div>
    <div class="btn btn-inline pull-right">Preview</div>
    <div class="btn btn-inline pull-right">Save and Close</div>
</div>

问题CompositeView:

<div class="editor ui-sortable">

</div>

问题CompositeView:

<div class="row">
  <div class="col-sm-offset-1 col-sm-1">
    <div class="step-number">1</div>
  </div>
  <div class="col-sm-8">
    <div class="question-editor" id="editor-1000" data-question-id="1000">
      <div class="question-heading">
        <div  id="type" class="type">
          <div class="btn-group">
            <button type="button" id="question-select" class="btn dropdown-toggle" data-toggle="dropdown">
            <% if @single_response: %>
            Single Select 
            <% else: %>
            Multiple Select 
            <% end %>
            <span class="caret"></span></button>
            <ul class="dropdown-menu" role="menu">
              <li>
                <a href="#" class="single-select">Single Select</a>
              </li>
              <li>
                <a href="#" class="multi-select">Multiple Select</a>
              </li>
            </ul>
          </div>
          <div class="btn-group">
            <button type="button" id="question-select"><i class="fa fa-cog"></i>
          </div>
        </div>
        <div class="controls">
          <div class="btn delete-question-button">
            <i class="fa fa-times"></i>
          </div>
        </div>
      </div>
      <div class="question-title">
        <input id="question-title" type="text" placeholder="Question text" value="<%= @title %>">
      </div>
      <div class="answers shadowed-scrollbox">
        <div class="answer-container"></div>
        <div class="btn add-answer">
          <i class="fa fa-plus-square"> Add Answer</i>
        </div>
      </div>
      <div class="answer-options">
        <input type="checkbox" id="randomize-1000" class="randomize-answers">
        <label for="randomize-1000">Randomize answer order
        <br>
      </div>
    </div>
  </div>
</div>

答案视图:

<div class="row">
  <div class="col-sm-9">
    <input id="answer-title" type="text" placeholder="Answer text" class="answer" value="<%= @title %>">
  </div>
  <div class="col-sm-3">
    <div id="answer-buttons" class="btn-group">
      <a class="btn manage-skip"><i class="fa fa-code-fork"></i></a>
      <a class="btn btn-danger delete-button"><i class="fa fa-times"></i></a>
    </div>
  </div>
</div>

面板视图:

<i class="fa fa-plus-square"> Add Question</i>

编辑

我还注意到我可以将删除逻辑直接放在视图中,这样我就可以实际删除答案。看起来这个逻辑似乎真的属于一个控制器,通过冒泡事件。

class List.Answer extends App.Views.ItemView
    template: "surveys/list/_answer"
    className: "answer-container"

    events:
      "click a.delete-button": "deleteAnswer"

    deleteAnswer: (e) ->
      e.preventDefault()
      if confirm "Are you sure you want to delete #{@model.get("title")}?" then @model.destroy() else false
      @trigger "answer:delete:clicked", @model
      console.log "deleteAnswer"

1 个答案:

答案 0 :(得分:3)

我明白了。您必须在嵌套复合视图初始化方法中监听子视图事件,然后将其冒泡到控制器。

所以我可以触发那么事件&gt;然后再将它重新触发到控制器:

class List.Answer extends App.Views.ItemView
    template: "surveys/list/_answer"
    className: "answer-container"

    triggers:
      "click a.delete-button": "answer:delete:clicked"

  class List.Question extends App.Views.CompositeView
    template: "surveys/list/_question"
    id: "1000"
    className: "step"
    initialize: ->
      @collection = @model.get("answers")
      @model.set(question_number: @model.collection.indexOf(@model) + 1)
      @on "childview:answer:delete:clicked", (child, args) =>
        args.collection = @model.get('answers')
        @trigger "answer:delete:clicked", args

听取并采取行动:

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

      @listenTo questionView, "childview:answer:delete:clicked", (child, args, answers) ->
        model = args.model
        answers = args.collection
        answers.remove(model)
        model.destroy()
相关问题