How to Use 404 Page in Your Ember.js Application

Billy Heaton 2 min read

Cases when a 404 page is needed

  1. When the URL does not match any defined routes, the application should render a 404 page.
  2. When a route's model hook has a call to this.store or Em.$.ajax and the result is a promise that is rejected perhaps the application should show a 404 page.

For example, when your adapter cannot find the resource that a route is expected to fetch. Ember.js routes may use an error action to transition to a 404 page. This will support a route which fails to transition due to a rejected promise caused by one or more of the route's hooks, e.g. model.

Catch-all route

To address the first case (above), when a given url doesn't match any route, define the last route in your router using a wildcard globbing route.

I setup a route for not-found in my router. The last route uses the wildcard /*path to catch any text string not already matched by other routes or resources. See the 'not-found' route in the router example below.

Router.map(function () {
  this.route('about');
  this.resource('posts', function () {
    this.resource('post', { path: ':post_slug' });
  });
  this.route('not-found', { path: '/*path' });
});

When the wildcard path matches a url that should result in the application rendering a 404 page, the (404) not-found route utilizes the redirect hook in order to transition to the url /not-found. My app has a Route prototype (app/routes/not-found.js) which is mapped to the 'non-found' route:

import Ember from 'ember';

export default Ember.Route.extend({
  redirect: function () {
    var url = this.router.location.formatURL('/not-found');
    if (window.location.pathname !== url) {
      this.transitionTo('/not-found');
    }
  }
});

The result is that the application renders a not-found template (templates/not-found.hbs) with a link to my archives page.

<h1>404 Not Found</h1>
<p>
  Perhaps you have a link that has changed, see {{#link-to 'posts'}}Archives{{/link-to}}.
</p>

Error in a route hook

Any route having a hook (e.g. model, beforeModel, afterModel) that results in a rejected promise, can use the error action to transition to the 404. See the Ember.Route error event doc page.

Define the action, log the error and transition to the '/not-found' page

import Ember from 'ember';

export default Ember.Route.extend({
  actions: {
    error: function (error) {
      Ember.Logger.error(error);
      this.transitionTo('/not-found');
    }
  }
});

Here is my 404 page: http://pixelhandler.com/not-found.

About the Author

Billy Heaton
Billy Heaton

Software engineer with two decades of experience who favors Ruby and JavaScript to build web applications