2012-01-10 15 views
31

Sto tentando di creare una vista Backbone.js basata su un modal bootstrap di Twitter, che utilizza la delega degli eventi automatici di Backbone tramite l'attributo events della vista.Utilizzo di bootstrap-modal come vista Backbone.js

Purtroppo, bootstrap-modal sembra rompere delegazione evento di Backbone come si clona il codice HTML vista prima di visualizzare il modal:

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

mio punto di vista:

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

La corrispondente (baffi) template 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 vengono chiamati quando vengono attivati ​​i rispettivi eventi.

Qualche idea?

+0

C'è un callback "aperto" di qualche tipo che è possibile utilizzare per riempire il modal con HTML? In pratica bypassare la clonazione (o almeno la parte della clonazione che sta rovinando 'delegate'). –

+0

Sì, cf. http://twitter.github.com/bootstrap/1.4.0/bootstrap-modal.js. Sfortunatamente, l'evento show viene chiamato prima del clone (e non ricevo l'evento mostrato a causa del problema originale). –

+0

Che dire dell'evento 'shown'? "Questo evento viene attivato quando la modal è stata resa visibile all'utente (attenderà il completamento delle transizioni di CSS)." –

risposta

17

Allright, quindi la soluzione è stata piuttosto semplice:

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 

Riassumendo le cose, la chiave è quello di dividere che mostra il modal in due fasi dando la possibilità di assegnare @el e invocare @delegateEvents() poi prima di renderlo visibile . @el.modal(true) può essere utilizzato per ottenere l'accesso all'oggetto che controlla il modale, ad esempio per nasconderlo programmaticamente.

+1

Ho dovuto aggiungere questo. $ el = $ (this.el); prima della riga @delegateEvents(). delegateEvents sembra utilizzarlo. $ el, invece di this.el e senza questa linea probabilmente fa riferimento a elementi errati. –

+1

Ho anche dovuto usare $ ("# myModal"). Modal ("nascondi"); per nascondere il modale. Con this.modal (true) .hide() per lo sfondo diventa nero e la finestra di dialogo attuale rimane al suo posto. Immagino che queste differenze potrebbero essere dovute a differenze nei motori dei modelli. Sto usando JsViews e aggiungo il modal in questo modo: this.el = $ ($. Rendering ["myTemplate"] (this.model.toJSON())). Modal ({...}); –

+0

Juha Palomäki: Immagino che tu stia usando Bootstrap 2, che era ancora in fase di sviluppo quando ho scritto la risposta di cui sopra e ho bisogno di alcune modifiche. Estenderò la mia risposta con il mio approccio Bootstrap 2 ... –

Problemi correlati