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

标签 javascript backbone.js marionette

我正在开发一个基本的调查应用程序来学习 Marionette/很好地掌握嵌套模型(答案 > 问题 > 调查)。我正在使用主干关系来完成此任务。

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

通常,当我只使用一个 CompositeView 时,我可以在 View 中这样说:

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

然后在 Controller 中

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

但是这种模式似乎不适用于我当前的结构。我还尝试了单击删除按钮时触发事件的途径>手动触发事件,但这除了正确登录到控制台之外不起作用。

有什么想法我哪里出错了吗?非常感谢任何帮助!

Controller :

@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

布局 View :

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

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

横幅 View :

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

面板 View :

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

编辑

我还注意到,我可以将删除逻辑直接放在 View 中,这样我就可以实际删除答案。但看起来这个逻辑确实属于通过冒泡事件而存在于 Controller 中。

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"

最佳答案

我明白了。您必须在嵌套复合 View 初始化方法中监听 subview 事件,然后将其冒泡到 Controller 。

所以我可以触发事件 > 然后将其再次重新触发到 Controller :

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

关于javascript - Marionette 嵌套 CompositeView 在 CompositeView 事件触发/冒泡中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25109687/

相关文章:

backbone.js - 如何在 CollectionView 中呈现依赖于 DOM 的 View ?

javascript - 在 Marionette 中从另一个应用程序调用一个应用程序的 View

javascript - 如何使用 koa ctx body 进行多个响应?

javascript - 如何根据预先确定的约束值自定义热图颜色?

javascript - Hammer JS 不适用于主干

javascript - Backbone 验证将输入添加到验证

javascript - 是什么让布局在 Marionette.js 中呈现?

javascript - 仅为两个不同的子域设置 cookie

javascript - 如何让 Chrome 扩展在页面加载时自动点击按钮?

javascript - 将模型添加到集合中