There are 2 comments in this discussion.
Read and join this discussion
Example code using Twitter Bootstrap with Ember.js 1.0.0-rc.1 and Ember Data (See Update for helpful links for later versions of Ember.js)
There is now a recipe for how to do this (sans Bootstrap) in the official Ember.js Cookbook. You should be able to adjust that approach to work with Bootstrap by using Bootstrap CSS modal classes.
This was written to when 1.0.0-pre4 was current, but has working sample code has been updated to point at 1.0.0-rc.1 and confirmed to work. Thanks for debugging help from dogawaf in #emberjs IRC.
These are purposely fairly standard routes for a simple Ember.js application (if you are using 1.0.0-pre4 and later).
There isn't anything here that assumes that the
posts.new or the
post.edit routes will be presented as modals. That's as it should be, but they are declared as distinct states that our application is in. This buys a lot, as we will see.
As you might guess, in this Ember.js simple blog application, the new and edit form implementation are exactly the same. Ember.js is smart enough in its conventions that we can use the same form template to handle both.
The template uses Twitter Bootstrap specific CSS classes that specify "modal" in them to be presented in modal windows, but otherewise there is nothing here that is out of the ordinary HTML augmented with Bootstrap and Ember.js handlebars code.
There are couple things to note though. The template uses the
action helper in a few places to wire up some events that we will later support in our route handlers;
Ember.Textfield helpers also have their values bound to
content.body which correspond to our Post model's properties. In other words, content is set to an instance of our Post model. This is pretty easy to do with the new router and route handlers.
Let's take a look:
Basically the route handlers take advantage of Ember.js's convention that the
model property will be set to the generated controller's
content by default (and therefore made available to our template as
In other words, all we have to do to set up the data for the form template is define our
model properties in our route handlers.
The route handlers also have some shared code in the
PostsFormable mixin. It starts with the
renderTemplate declaration. I'll come back to that in a second.
action helper's calls to "cancel" and "submit"? The mixin's code contains the route handler's events declaration that has the code that handles them.
cancel, the instance of the
post that we created for the
post.new is cleared out and then the application is changed to the
posts route (i.e. the list of posts).
submit, the instance of the
post is commited, thus pushed to our data store, and permanently added to our application, and again we switch to the
Neither of them have anything specifically to do with the fact that we using modals for our presentation. It's handling the data and state details of our application without being concerned about the presentation of the form per se. Nicely separated from our templates and views.
Where the mixin does connect with presentation is simply to say that the route handlers' routes will both render using the
posts/form template and that they should be connected to the
outlet named 'modal'.
This is because we are differing from the default template naming convention where routes are paired with a template with the same name. This allows us to re-use the
posts/form template for both
post.edit routes and be a bit DRYer.
So far all we have done to set up our
post.edit forms to be modal is use a different named
outlet and add some CSS classes in our template's HTML, but there is one last essential piece to complete things; the
From the Ember.js guide for Views' introduction:
Views in Ember.js are typically only created for the following reasons:
- When you need sophisticated handling of user events
Events in this context are user interaction events, such as clicks, mouseovers, etc. So when a user clicks on a link or button to get the form, we want to use a modal transition and presentation.
Since our forms represent distinct routes in our applicaton, we use the
linkTo helper to change the application to this route. A link to our form may be in multiple places in our application and so it would add a lot of complexity to handle it in the view where the user clicks from (alternatively you could define a helper to be DRY, but its not worth it in this case), so this is subprime.
Turns out Ember.js can handle this really elegantly with two view events on the view that represents our form; when the view's HTML element is added to the DOM and when the view's HTML element is pulled out of the DOM.
First we wire up a bit of the HTML that ties into Bootstrap's modal handling. Since our view corresponds directly to form semantically in HTML, we switch the view's tag to "form". This will wrap our template in a form tag.
However what really triggers our modal and cleans them up when we dismiss or submit our forms is
How this works is that when our application switches to a route that has the
posts/form template (and thus the
App.PostsFormView), this view's element is added to the DOM and the
didInsertElement callback function is then run. There is a parallel process that happens when our applications switches out of route that uses the
willDestroyElement is called just before our view's element is pulled from the DOM.
All these two callbacks have to do is run the code that shows or hides the modal like you would with standard Bootstrap.
One neat detail is that Ember.js provides with a shortcut to only this view's HTML via the
And that is it. Enjoy!