Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using bootstrap-modal as Backbone.js view

I am attempting to create a Backbone.js view based on a Twitter bootstrap-modal, which makes use of Backbone's automatic event delegation via the events attribute of the view.

Unfortunately, bootstrap-modal seems to break Backbone's event delegation as it clones the view HTML before displaying the modal:

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

My view:

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

The corresponding (Mustache) HTML template:

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

Neither save nor shown are called when the respective events are triggered.

Any ideas?

like image 641
Thilo-Alexander Ginkel Avatar asked Jan 10 '12 22:01

Thilo-Alexander Ginkel


1 Answers

Allright, so the solution is was rather 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 

Summing things up, the key is to split showing the modal into two steps giving the possibility to assign @el and invoke @delegateEvents() afterwards before making it visible. @el.modal(true) can be used to get access to the object controlling the modal, e.g., to programmatically hide it.

like image 178
Thilo-Alexander Ginkel Avatar answered Oct 07 '22 18:10

Thilo-Alexander Ginkel