Ember Octane is here! A lot has changed since Ember 3.14, including these Guides. Read more in the Ember Blog.

Old Guides - You are viewing the guides for Ember v1.13.0. VIEW v3.15.0
Edit Page

Naming Conventions


Ember.js uses a runtime resolver to wire up your objects without a lot of boilerplate. As a developer, this resolver will work automatically if you place code in conventional locations within your project.

You can usually guess the names and locations, but this guide outlines, in one place, all of the naming conventions.

The Application

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

If your app provides a route at app/routes/application.js 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 route:application Route, which is an Ember.Route object, implements the setupController hook.

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

export default Ember.Route.extend({
  model() {
    return { title: "Hello World" };
  }
});
export default Ember.Controller.extend({
  appName: 'My First Example'
});
<h1>{{appName}}</h1>
<h2>{{model.title}}</h2>

In Ember.js applications, you will always provide your objects as classes, and the framework is responsible for instantiating them and providing them to your templates at runtime through the resolver.

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:

var Router = Ember.Router.extend();

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

export default Router;

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

  • app/routes/favorites.js
  • app/controllers/favorites.js
  • app/templates/favorites.hbs

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

If your app provides a route:favorites, the framework will invoke it before rendering the template. Yes, this is a bit repetitive.

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

Here's an example:

import ajax from 'ic-ajax';

export default Ember.Route.extend({
  model() {
    // the model is an Array of all of the posts
    // fetched from this url
    return ajax('/a/service/url/where/posts/live');
  }
});

In this example, we didn't provide a controller:favorites. 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 Ember.ArrayController as if it was the model itself. The benefit of this is that you can replace the controller's model at any time without having to directly notify templates and components of the change.

The template can iterate over the elements of the controller:

<ul>
{{#each controller as |item|}}
  <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:

var Router = Ember.Router.extend();

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

export default Router

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

  • app/routes/post.js
  • app/controllers/post.js
  • app/templates/post.hbs

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).

import ajax from 'ic-ajax';

export default Ember.Route.extend({
  model(params) {
    return ajax('/my-service/posts/' + params.post_id);
  },

  serialize(post) {
    return { post_id: Ember.get(post, '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 looks for app/models/post.js). 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/routes/post.js), Ember.js will still render the app/templates/post.hbs template with the app's instance of app/controllers/post.js.

If you don't specify the controller (app/controllers/post.js), 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. As of 1.11, ObjectControllers are deprecated and if you try to use its proxy feature you will get a warning. Please, take a look at the deprecations guide for more detailed information.

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

Nesting

You can nest routes:

var Router = Ember.Router.extend();

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

export default Router

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

Route Name Convention
posts
app
 ├── controllers/
 │   └── posts.js  
 ├── routes/
 │   └── posts.js  
 └── templates/
     └── posts.hbs
            
posts.favorites
app
 ├── controllers/
 │   └── posts/  
 │       └── favorites.js  
 ├── routes/
 │   └── posts/
 │       └── favorites.js  
 └── templates/
     └── posts/
         └── favorites.hbs
          
posts.post
app
 ├── controllers/
 │   └── posts/  
 │       └── post.js  
 ├── routes/
 │   └── posts/
 │       └── post.js  
 └── templates/
     └── posts/
         └── post.hbs
            

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:

var Router = Ember.Router.extend();

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

export default Router;

It is the equivalent of:

var Router = Ember.Router.extend();

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

export default Router;

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

  • app/routes/index.js
  • app/controllers/index.js
  • app/templates/index.hbs

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:

var Router = Ember.Router.extend();

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

export default Router;

Is the equivalent of:

var Router = Ember.Router.extend();

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

export default Router;

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

  • app/routes/posts/index.js
  • app/controllers/posts/index.js
  • app/templates/posts/index.hbs

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.