2012-01-10 27 views
31

Estoy intentando crear una vista de Backbone.js basada en una rutina de arranque de Twitter, que hace uso de la delegación automática de eventos del Backbone a través del atributo events de la vista.Uso de bootstrap-modal como vista Backbone.js

Desafortunadamente, arranque-modal parece romper delegación de eventos de la espina dorsal, ya que clona la vista HTML antes de mostrar el modal:

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

Mi opinión:

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}) 
    @ 

El (bigote) plantilla HTML correspondiente :

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

ni save ni shown se invocan cuando se activan los eventos respectivos.

¿Alguna idea?

+0

¿Hay alguna devolución de llamada "abierta" de algún tipo que pueda usar para completar el modal con HTML? Básicamente omite la clonación (o al menos la parte de la clonación que está atornillando 'delegar'). –

+0

Sí, cf. http://twitter.github.com/bootstrap/1.4.0/bootstrap-modal.js. Lamentablemente, se llama al evento show antes del clon (y no recibo el evento mostrado debido al problema original). –

+0

¿Qué pasa con el evento 'shown'? "Este evento se dispara cuando el modal se ha hecho visible para el usuario (esperará a que se completen las transiciones css)". –

Respuesta

17

De acuerdo, así que la solución es más bien simple:

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 

Resumiendo las cosas, la clave es dividida con los modales en dos pasos que da la posibilidad de asignar @el e invocar @delegateEvents() después, antes de hacer visible . @el.modal(true) se puede usar para obtener acceso al objeto que controla el modal, por ejemplo, para ocultarlo mediante programación.

+1

Tuve que agregar esto. $ el = $ (this.el); antes de la fila @delegateEvents(). delegateEvents parece estar usando this. $ el, en lugar de this.el y sin esta línea, probablemente esté haciendo referencia a elementos erróneos. –

+1

También tuve que usar $ ("# myModal"). Modal ("ocultar"); para ocultar el modal. Con this.modal (true) .hide() por fondo se vuelve negro y el diálogo real permanece en su lugar. Supongo que estas diferencias podrían deberse a diferencias en los motores de plantillas. Estoy usando JsViews y agregando el modal de esta manera: this.el = $ ($. Render ["myTemplate"] (this.model.toJSON())) modal ({...}); –

+0

Juha Palomäki: Supongo que está usando Bootstrap 2, que aún estaba en desarrollo cuando escribí la respuesta anterior y necesita algunos cambios. Extenderé mi respuesta con mi enfoque de Bootstrap 2 ... –

Cuestiones relacionadas