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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With