【问题标题】:Using bootstrap-modal as Backbone.js view使用 bootstrap-modal 作为 Backbone.js 视图
【发布时间】:2012-02-07 08:44:16
【问题描述】:

我正在尝试基于 Twitter 引导模式创建一个 Backbone.js 视图,它通过视图的 events 属性利用 Backbone 的自动事件委托。

不幸的是,bootstrap-modal 似乎破坏了 Backbone 的事件委托,因为它在显示模式之前克隆了视图 HTML:

that.$element
      .appendTo(document.body)
      .show()

我的看法:

App.Views.ProjectsNav ||= {}

class App.Views.ProjectsNav.NewProjectView extends Backbone.View
  events: {
    'click .save': 'save',
    'shown':       'shown'
  }

  save: (e) ->
    ...
    false

  shown: () ->
    App.Helpers.Forms.setFocus($(@el), true)
    false

  render: () ->
    $(@el).html(ich.nav_edit_project_template(@model.toJSON()))
    @$('.modal').modal({'show': true, 'keyboard': true, 'backdrop': true})
    @

对应的(Mustache)HTML模板:

<div class="modal hide" style="display: none; ">
  <div class="modal-header">
    <a href="#" class="close">×</a>
    <h3>New Project</h3>
  </div>
  <div class="modal-body form-stacked">
    <label for="name">Name</label> <input type="text" name="name" value="{{name}}"/><input type="hidden" name="lock_version" value="{{lock_version}}"/>
  </div>
  <div class="modal-footer">
    <a href="javascript:void(0)" class="save btn primary">Create</a>
    <a href="javascript:void(0)" class="cancel btn secondary">Cancel</a>
  </div>
</div>

当相应的事件被触发时,saveshown 都不会被调用。

有什么想法吗?

【问题讨论】:

  • 是否有某种“打开”回调可以用来用 HTML 填充模式?基本上绕过克隆(或者至少是克隆的一部分搞砸了delegate)。
  • 是的,参见。 twitter.github.com/bootstrap/1.4.0/bootstrap-modal.js。不幸的是,在克隆之前调用了 show 事件(由于原始问题,我没有得到显示的事件)。
  • shown 事件怎么样? “当模式对用户可见时触发此事件(将等待 css 转换完成)​​。”
  • 好吧,当 HTML 片段被移动到 DOM 中的另一个位置 (document.body) 后触发了 shown 事件,主干视图没有得到它的回调调用 (@el不再指向那里)。
  • 你能创建模态,然后把主干视图放在里面吗?

标签: javascript backbone.js coffeescript twitter-bootstrap


【解决方案1】:

好的,所以解决方法很简单:

App.Views.ProjectsNav ||= {}

class App.Views.ProjectsNav.NewProjectView extends Backbone.View
  tagName: 'div'

  events: {
    'click .save':   'save',
    'click .cancel': 'hide',
    'hidden':        'hidden',
    'shown':         'shown'
  }

  initialize: (options) ->
    super(options)
    @collection = options.collection

  hide: () ->
    @el.modal(true).hide()
    false

  save: (e) ->
    ...
    @model.save(attrs, {
      success: (project) =>
        @model = project
        @collection.add(@model)
        @hide()
      error: (project) =>
        alert('Something went wrong: ' + project)
      }
    )
    false

  render: () ->
    @el = ich.nav_edit_project_template(@model.toJSON()).modal('keyboard': true, 'backdrop': true)
    @delegateEvents()
    @el.modal('show': true)
    @

  hidden: () ->
    @remove()
    false

  shown: () ->
    App.Helpers.Forms.setFocus($(@el), true)
    false

总结一下,关键是将显示模式分成两个步骤,从而可以分配@el,然后在使其可见之前调用@delegateEvents()@el.modal(true) 可用于访问控制模式的对象,例如,以编程方式隐藏它。

【讨论】:

  • 我必须添加 this.$el = $(this.el);在 @delegateEvents() 行之前。 delegateEvents 似乎使用的是 this.$el,而不是 this.el,而且如果没有这一行,它可能引用了错误的元素。
  • 我还必须使用 $("#myModal").modal("hide");隐藏模式。使用 this.modal(true).hide() 由背景变为黑色,实际对话框保持原位。我猜这些差异可能是由于模板引擎的差异。我正在使用 JsViews 并以这种方式添加模式: this.el = $($.render["myTemplate"](this.model.toJSON())).modal({...});
  • Juha Palomäki:我猜你正在使用 Bootstrap 2,当我写上述答案时它仍在开发中,需要一些更改。我将用我的 Bootstrap 2 方法扩展我的答案......
  • 只需使用 view.setElement 代替 '@el = ...' 和 '@delegateEvents()'
猜你喜欢
  • 2012-06-30
  • 1970-01-01
  • 2012-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-16
  • 1970-01-01
相关资源
最近更新 更多