URLs are very important in just about every type of web application. A well designed URL scheme should describe the user’s location within the hierarchy of the application.

In a modern web application, the user should be able to navigate by either taking an action through the user interface, using a browser function or typing the URL directly. Traditionally this has not always been easy in Javascript heavy client-side applications.

Ember has an excellent router that abstracts this complexity to provide you with an easy to use interface.

In today’s tutorial we are going to be looking at the Ember router.

Logging route transitions

Before we get into today’s tutorial, the first thing you should do is install the Ember Inspector.

The Ember Inspect allows you to see all of the routes that are defined in your application, information about the templates, controllers and models, inspect the objects of your application, plus much, much more.

You will also want to add the LOG_TRANSITIONS property:

var App = Ember.Application.extend({  
modulePrefix: config.modulePrefix,  
podModulePrefix: config.podModulePrefix,  
Resolver: Resolver,  
LOG_TRANSITIONS: true  
});  

Now when you move between pages of your application you will see helpful debug information in the console.

What is the job of the router?

In an Ember application, the router is very important. The router is responsible for displaying templates, loading data and setting up the application state.

In order for Ember to know about the routes of our application, we need to first define them in the routes.js file:

Router.map(function() {

});  

If you’ve been following a long with the last couple of articles, you will know that we were able to hit the / route without it being defined. This is one of the default routes of an Ember application, so you don’t need to define it.

Defining Routes

To define a new route in our application, we can simply call the route() method inside the map() method of the Router and pass the name of our desired route:

Router.map(function() {  
this.route(‘contact’);  
});  

This will created a named route called contact. By default this will route to the /contact URL.

If you want to override this default URL to provide a different URL, you can do so by passing an optional second object parameter:

Router.map(function() {  
this.route(‘contact’, {path:’/contact-us’);  
});  

In last week’s tutorial we looked at using the {{#link-to}} View helper.

To use our new contact route in a View we can write the following in the template:

{{#link-to ‘contact’}}Contact{{/link-to}}  

This will generate the following HTML:

<a href="/contact">Contact</a>  

Defining Resources

Ember applications have the idea of routes and resources.

As we’ve just seen above, a route is just a single URL. A resource is a collection of routes that describe a resource of the application.

For example, in Cribbb, we might have the following resource:

App.Router.map(function() {  
this.resource(‘posts’, { path: ‘/posts’ }, function() {  
this.route(‘new’);  
});  
});  

The nested new route would resolve as /posts/new.

You can also have multiple levels of route nesting:

App.Router.map(function() {  
this.resource(‘post’, { path: ‘/post/:post_id’ }, function() {  
this.route(‘edit’);  
this.resource(‘comments’, function() {  
this.route(‘new’);  
});  
});  
});  

Dynamic segments

When you want to access a single item of a resource through the URL, you typically pass the id as a parameter along the lines of /posts/123 where 123 is the id.

You would define a route with a dynamic segment like this:

App.Router.map(function() {  
this.resource(‘posts’);  
this.resource(‘post’, { path: ‘/post/:post_id’ });  
});  

This is such a common pattern in web applications that Ember will automatically know to find the post with the id that was passed in through the URL.

Understanding Ember’s defaults

One of the best things about Ember is that it follows a Convention over Configuration policy. This means if you follow the naming conventions that are already established, things will just automatically work.

A good example of this convention can be seen when defining routes.

If you define a route named post, Ember will automatically make the following assumptions:

  • Your URL is /post
  • Your Controller is PostController
  • Your Route is PostRoute
  • Your Template is post

This can seem restrictive at first, but honestly convention over configuration is a much better approach. When developing a web application you have to make a million decisions, you shouldn’t have to think about wiring up these components.

Customising Routes

If you would like to customise the behaviour of a route you can create a new Ember.Route object:

App.PostRoute = Ember.Route.extend({

});  

As I mentioned above, due to the naming conventions of Ember, the application will automatically know to use this class for the post route.

We will be looking into this more in next week’s tutorial.

Conclusion

Routing requests through your application is common to all web applications. The job of the framework is to deal with this boilerplate complexity so you can get on with working on your application.

Ember’s Router is easy to use and understand. What’s more, if your application follows many of the common standards of a modern web application, the majority of the functionality should work straight out of the box.

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.

To view a full listing of the tutorials in this series, click here.