ContributorsLast modified on: Mar 25, 2016
farhan687

Ember.js uses naming conventions to wire up your objects without a lot of boilerplate. You will want to use these conventional names for your routes, controllers and templates.

You can usually guess the names, but this guide outlines, in one place, all of the naming conventions. In the following examples ‘App’ is a name that we chose to namespace or represent our Ember application when it was created, but you can choose any name you want for your application. We will show you later how to create an Ember application, but for now we will focus on conventions.

The Application

When your application boots, Ember will look for these objects:

  • App.ApplicationRoute
  • App.ApplicationController
  • the application template

Ember.js will render the application template as the main template. If App.ApplicationController is provided, Ember.js will set an instance of App.ApplicationController as the controller for the template. This means that the template will get its properties from the controller.

If your app provides an App.ApplicationRoute, Ember.js will invoke the router’s hooks first, before rendering the application template. Hooks are implemented as methods and provide you access points within an Ember object’s lifecycle to intercept and execute code to modify the default behavior at these points to meet your needs. Ember provides several hooks for you to utilize for various purposes (e.g. model, setupController, etc). In the example below App.ApplicationRoute, which is an Ember.Route object, implements the setupController hook.

Here’s a simple example that uses a route, controller, and template:

App.ApplicationRoute = Ember.Route.extend({
  setupController: function(controller) {
    // `controller` is the instance of ApplicationController
    controller.set('title', "Hello world!");
  }
});

App.ApplicationController = Ember.Controller.extend({
  appName: 'My First Example'
});
<!-- application template -->
<h1>{{appName}}</h1>

<h2>{{title}}</h2>

In Ember.js applications, you will always specify your controllers as classes, and the framework is responsible for instantiating them and providing them to your templates.

This makes it super-simple to test your controllers, and ensures that your entire application shares a single instance of each controller.

Simple Routes

Each of your routes will have a controller, and a template with the same name as the route.

Let’s start with a simple router:

App.Router.map(function() {
  this.route('favorites');
});

If your user navigates to /favorites, Ember.js will look for these objects:

  • App.FavoritesRoute
  • App.FavoritesController
  • the favorites template

Ember.js will render the favorites template into the {{outlet}} in the application template. It will set an instance of the App.FavoritesController as the controller for the template.

If your app provides an App.FavoritesRoute, the framework will invoke it before rendering the template. Yes, this is a bit repetitive.

For a route like App.FavoritesRoute, you will probably implement the model hook to specify what model your controller will present to the template.

Here’s an example:

App.FavoritesRoute = Ember.Route.extend({
  model: function() {
    // the model is an Array of all of the posts
    return this.store.find('post');
  }
});

In this example, we didn’t provide a FavoritesController. Because the model is an Array, Ember.js will automatically supply an instance of Ember.ArrayController, which will present the backing Array as its model.

You can treat the ArrayController as if it was the model itself. This has two major benefits:

  • You can replace the controller’s model at any time without having to directly notify the view of the change.
  • The controller can provide additional computed properties or view-specific state that do not belong in the model layer. This allows a clean separation of concerns between the view, the controller and the model.

The template can iterate over the elements of the controller:

<ul>
{{#each item in controller}}
  <li>{{item.title}}</li>
{{/each}}
</ul>

Dynamic Segments

If a route uses a dynamic segment (a URL that includes a parameter), the route’s model will be based on the value of that segment provided by the user.

Consider this router definition:

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

In this case, the route’s name is post, so Ember.js will look for these objects:

  • App.PostRoute
  • App.PostController
  • the post template

Your route handler’s model hook converts the dynamic :post_id parameter into a model. The serialize hook converts a model object back into the URL parameters for this route (for example, when generating a link for a model object).

App.PostRoute = Ember.Route.extend({
  model: function(params) {
    return this.store.find('post', params.post_id);
  },

  serialize: function(post) {
    return { post_id: post.get('id') };
  }
});

Because this pattern is so common, it is the default for route handlers.

  • If your dynamic segment ends in _id, the default model hook will convert the first part into a model class on the application’s namespace (post becomes App.Post). It will then call find on that class with the value of the dynamic segment.
  • The default behaviour of the serialize hook is to replace the route’s dynamic segment with the value of the model object’s id property.

Route, Controller and Template Defaults

If you don’t specify a route handler for the post route (App.PostRoute), Ember.js will still render the post template with the app’s instance of App.PostController.

If you don’t specify the controller (App.PostController), Ember will automatically make one for you based on the return value of the route’s model hook. If the model is an Array, you get an ArrayController. Otherwise, you get an ObjectController.

If you don’t specify a post template, Ember.js won’t render anything!

Nesting

You can nest routes under a resource.

App.Router.map(function() {
  this.resource('posts', function() { // the `posts` route
    this.route('favorites');          // the `posts.favorites` route
    this.resource('post');            // the `post` route
  });
});

A resource is the beginning of a route, controller, or template name. Even though the post resource is nested, its route is named App.PostRoute, its controller is named App.PostController and its template is post.

When you nest a route inside a resource, the route name is added to the resource name, after a ..

Here are the naming conventions for each of the routes defined in this router:

Route Name Controller Route Template
posts PostsController PostsRoute posts
posts.favorites PostsFavoritesController PostsFavoritesRoute posts/favorites
post PostController PostRoute post

The rule of thumb is to use resources for nouns, and routes for adjectives (favorites) or verbs (edit). This ensures that nesting does not create ridiculously long names, but avoids collisions with common adjectives and verbs.

The Index Route

At every level of nesting (including the top level), Ember.js automatically provides a route for the / path named index.

For example, if you write a simple router like this:

App.Router.map(function() {
  this.route('favorites');
});

It is the equivalent of:

App.Router.map(function() {
  this.route('index', { path: '/' });
  this.route('favorites');
});

If the user visits /, Ember.js will look for these objects:

  • App.IndexRoute
  • App.IndexController
  • the index template

The index template will be rendered into the {{outlet}} in the application template. If the user navigates to /favorites, Ember.js will replace the index template with the favorites template.

A nested router like this:

App.Router.map(function() {
  this.resource('posts', function() {
    this.route('favorites');
  });
});

Is the equivalent of:

App.Router.map(function() {
  this.route('index', { path: '/' });
  this.resource('posts', function() {
    this.route('index', { path: '/' });
    this.route('favorites');
  });
});

If the user navigates to /posts, the current route will be posts.index. Ember.js will look for objects named:

  • App.PostsIndexRoute
  • App.PostsIndexController
  • The posts/index template

First, the posts template will be rendered into the {{outlet}} in the application template. Then, the posts/index template will be rendered into the {{outlet}} in the posts template.

If the user then navigates to /posts/favorites, Ember.js will replace the {{outlet}} in the posts template with the posts/favorites template.