I spent some time studying Discourse to find out how they do it. Mostly they have a single-modem modem, and the router processes events to show and hide the modal.
Here are some interesting bits:
discourse / application / assets / JavaScripts / discourse / routes / discourse_route.js
showModal: function(router, name, model) { router.controllerFor('modal').set('modalClass', null); router.render(name, {into: 'modal', outlet: 'modalBody'}); var controller = router.controllerFor(name); if (controller) { if (model) { controller.set('model', model); } controller.set('flashMessage', null); } }
discourse / application / assets / JavaScripts / discourse / routes / application_route.js
events: { editCategory: function(category) { Discourse.Route.showModal(router, 'editCategory', category); router.controllerFor('editCategory').set('selectedTab', 'general'); }
discourse / application / assets / JavaScripts / discourse / view / modal / modal_body_view.js
Discourse.ModalBodyView = Discourse.View.extend({ // Focus on first element didInsertElement: function() { $('#discourse-modal').modal('show'); var controller = this.get('controller'); $('#discourse-modal').on('hide.discourse', function() { controller.send('closeModal'); }); $('#modal-alert').hide(); var modalBodyView = this; Em.run.schedule('afterRender', function() { modalBodyView.$('input:first').focus(); }); var title = this.get('title'); if (title) { this.set('controller.controllers.modal.title', title); } }, willDestroyElement: function() { $('#discourse-modal').off('hide.discourse'); } });
discourse / application / assets / javascripts / discourse / mixins / modal_functionality.js
Discourse.ModalFunctionality = Em.Mixin.create({ needs: ['modal'], flash: function(message, messageClass) { this.set('flashMessage', Em.Object.create({ message: message, messageClass: messageClass })); } });
Application / assets / JavaScripts / discourse / templates / modal / modal.js.handlebars
<div class="modal-header"> <a class="close" {{action closeModal}}><i class='icon-remove icon'></i></a> <h3>{{title}}</h3> </div> <div id='modal-alert'></div> {{outlet modalBody}} {{#each errors}} <div class="alert alert-error"> <button class="close" data-dismiss="alert">Γ</button> {{this}} </div> {{/each}}
And in their application.js.handlebars: {{render modal}}