31 votes

Utiliser bootstrap-modal comme vue Backbone.js

J'essaie de créer une vue Backbone.js basée sur une modalité Twitter bootstrap, qui utilise la délégation automatique d'événements de Backbone via la fonction events de la vue.

Malheureusement, bootstrap-modal semble casser la délégation d'événements de Backbone car il clone le HTML de la vue avant d'afficher la fenêtre modale :

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

Mon point de vue :

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

Le modèle HTML correspondant (Moustache) :

<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 l'un ni l'autre save ni shown sont appelées lorsque les événements respectifs sont déclenchés.

Des idées ?

17voto

D'accord, la solution est donc assez 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

En résumé, il s'agit de diviser l'affichage de la modalité en deux étapes, en donnant la possibilité d'assigner @el et invoquer @delegateEvents() avant de le rendre visible. @el.modal(true) peut être utilisé pour accéder à l'objet contrôlant la fenêtre modale, par exemple pour la masquer par programme.

8voto

Alexandra Points 869

Étant donné que je travaille sur quelque chose de très similaire, j'ai été heureux de trouver la question de Thilo-Alexander Ginkel sur Stack Overflow. En cherchant de l'aide supplémentaire, j'ai trouvé le récent billet de Derick Bailey à propos de gérer un dialogue modal avec Backbone a semblé pertinente. J'espère qu'en publiant ce lien ici, j'aiderai d'autres personnes.

Alexandra

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X