Apr 27, 2015
Table of contents:
Last week we looked at the basics of routing in Ember. Routing URLs is one of the core components of a framework because it is the URL that drives the behaviour of the application.
I mentioned last week that you don’t always have to specify things in Ember because certain defaults will be assumed.
This is convention over configuration, a trait of rapid application development that will make your life a lot easier.
To enable this to work, Ember implements some magic behind the scenes.
Today we are going to look at understanding this magic, as well as working with Route
objects.
Last week we looked at some of the conventions of Ember when defining routes.
For example, when you define a new named route of posts
, Ember will assume you will be be using:
/posts
PostsController
PostsRoute
posts
Last week when we were creating a new route, you might have noticed that everything seemed to work, despite the fact we did not create the PostsController
, PostsRoute
or posts
template.
If Ember does not find these files, it will generate them for you at run-time.
This means things will automatically work out of the box, but if you want to customise the behaviour of any of these objects, you can simply create your own object that will be used instead.
One of the really good things about using Ember CLI is that it comes with generators to create a lot of the boilerplate code and files you will need.
Open terminal and run the following command:
ember help generate
You should be presented with a list of all the generators you have available. You can even define your own blueprints that will be used instead of the default blueprints if you want to do something a slightly different way.
In order for an application to be useful, we’re going to need some data to work with.
One of the responsibilities of the Route
is to define the model.
So the first thing we can do is to generate a new resource:
ember g resource posts
This will generate a new resource named posts
.
This will create a couple of new files in your project, but we won’t worry about those for now. The only file we’ll be looking at right now should be the posts.js
file under the routes
directory:
import Ember from "ember";
export default Ember.Route.extend({});
If you run ember serve
and then fire up the browser and go to /posts
you should see that everything works, there is just nothing to display right now.
As I mentioned above, one of the responsibilities of the Route
is to provide the template with data.
We can do this be implementing the model
hook of the Route
object. The easiest way of doing this is to simply return an object of data items:
import Ember from "ember";
export default Ember.Route.extend({
model: function () {
return [
{
title: "Hello world",
body: "Nulla dolor ipsum, dapibus sed sodales sed, molestie eu metus.",
},
{
title: "My first post",
body: "Curabitur pellentesque enim et purus venenatis, ac gravida erat euismod.",
},
];
},
});
Now if you add the following code to your posts.hbs
file you should see the data rendered in the browser:
<ul>
{{#each post in model}}
<li>{{post.title}}</li>
{{/each}}
</ul>
Now of course you will not want to hardcode the data into your application because that would make the application pretty useless!
Typically you are going to load the data using an Ajax request or through a model layer such as Ember Data. However, for now we will simply work with hardcoded data to understand what’s going on under the hood. There is no point in trying to run before we can walk!
The Route
is also responsible for passing data to the Controller and for rendering the Template.
As I mentioned earlier, by default, Ember will make some assumptions about the names of the Controller and Template to use. If Ember can’t find these files, it will automatically generate them in-memory at run-time.
However, you might want to use a Controller or a Template that does not fit with Ember’s naming conventions. In order to do that, you can specify it in the Route
class.
To use a controller that is different to the Ember default you can specify the controllerName
property:
export default Ember.Route.extend({
controllerName: "article",
});
If you want to use a different template, you can implement the renderTemplate
hook:
export default Ember.Route.extend({
renderTemplate: function () {
this.render("highlightedArticle");
},
});
If you want to transition or redirect you can deal with this in the Route
by hooking on to one of the hooks.
Firstly you can transition before the model has been loaded using the beforeModel
hook:
export default Ember.Route.extend({
beforeModel: function () {
this.transitionTo("login");
},
});
Alternatively you can transition after the model has loaded if you need to determine whether to transition or not based upon the model instance:
export default Ember.Route.extend({
afterModel: function (posts, transition) {
if (posts.get("length") === 0) {
this.transitionTo("login");
}
},
});
One of the great things about Ember is the fact that a lot of the functionality will work straight out-of-the-box. It’s surprising how little code you actually need to write to get your Ember application up and running.
However, this is obviously a double-edged sword. Whilst working within these constraints makes for a wonderful experience, I’m sure everything won’t be so pretty if you try to stray from the beaten path.
This is a series of posts on building an entire Open Source application called Cribbb. All of the tutorials will be free to web, and all of the code is available on GitHub.