I have setup my application to use the ember routing architecture. My index pages looks like this (for simplicity sake)
script(type='text/x-handlebars', data-template-name='application')
div.container
{{outlet}}
and my ember app like this
window.App = Em.Application.create({
ApplicationController: Em.Controller.extend(),
ApplicationView: Ember.View.extend({
templateName: 'application'
}),
Router: Em.Router.extend({
root: Em.Route.extend({
doHome: (router, event) ->
router.transitionTo('home')
doInbox: (router, event) ->
router.transitionTo('inbox')
doInboxModal: (router, event) ->
$("#inbox").modal "show"
home: Em.Route.extend({
route: '/',
connectOutlets: (router, event) ->
router.get('applicationController').connectOutlet('home')
}),
inbox:Em.Route.extend({
route: '/inbox',
connectOutlets: (router, event) ->
router.get('applicationController').connectOutlet('inbox')
})
})
})
I have the home and inbox working fine, but first of all, I am doing jquery in my doInboxModal to show the modal inbox. And if I want to then have a button on the modal inbox to go to the actual inbox page, it won't work.
So, the question is, how do I properly use a Twitter Bootstrap Modal with ember routing?
When you route to a view, call the modal in the didInsertElement, which will load the modal..Assuming you want the modal to load on the inbox view
App.InboxView = Ember.View.extend({
didInsertElement: function(){
$("#my-modal").modal("show");
}
})
your updated router:
window.App = Em.Application.create({
ApplicationController: Em.Controller.extend(),
ApplicationView: Ember.View.extend({
templateName: 'application'
}),
Router: Em.Router.extend({
root: Em.Route.extend({
doHome: (router, event) ->
router.transitionTo('home')
doInbox: (router, event) ->
router.transitionTo('inbox')
home: Em.Route.extend({
route: '/',
connectOutlets: (router, event) ->
router.get('applicationController').connectOutlet('home')
}),
inbox:Em.Route.extend({
route: '/inbox',
connectOutlets: (router, event) ->
router.get('applicationController').connectOutlet('inbox')
})
})
})
Hope this helps...
Updated Answer
App.InboxView = Ember.View.extend({
templateName: "inbox",
addNewEmail: function(){
$("#my-modal").modal("show");
},
cancelNewEmail: function(){
$("#my-modal").modal("hide");
}
})
inbox.handlebars
<div id="inbox-container">
<!--
YOUR INBOX CONTENT
The modal declared below wont show up unless invoked
-->
<a {{action addNewEmail}}>New Email</a>
<a {{action cancelNewEmail}}>Cancel</a>
<div class="modal hide fade in" id="my-modal">
<!--
Put your modal content
-->
</div>
</div>
This way:
I have post on using Twitter Bootstrap modals with Ember.js if anyone wants further reference:
http://generali.st/en/site/topics/show/82-modal-forms-in-emberjs
Includes a working JSBin for the full source. Also has some strategies for DRYing up forms. IMO, the naming of things is a bit more conventional as well.
I spent some time dissecting Discourse to learn how they're doing it. Basically they have a singleton modal and the router handles events to display and hide the modal.
Here are the interesting bits :
discourse/app/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/app/assets/javascripts/discourse/routes/application_route.js
events: {
editCategory: function(category) {
Discourse.Route.showModal(router, 'editCategory', category);
router.controllerFor('editCategory').set('selectedTab', 'general');
}
discourse/app/assets/javascripts/discourse/views/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/app/assets/javascripts/discourse/mixins/modal_functionality.js
Discourse.ModalFunctionality = Em.Mixin.create({
needs: ['modal'],
/**
Flash a message at the top of the modal
@method blank
@param {String} name the name of the property we want to check
@return {Boolean}
**/
flash: function(message, messageClass) {
this.set('flashMessage', Em.Object.create({
message: message,
messageClass: messageClass
}));
}
});
app/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}}
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