How can I handle the error
Uncaught Error: No route matched the URL \'...\'
and show a custom 404 page?
Note: This questi
In Ember 2.x
Inside the App.Router.map
function, put code below the the end of the callback function.
this.route('your_handler_route_name', { path: '/*path' });
Now every route does NOT catche by the previous defined routes will be catched by your_handler_route_name
route.
You could try adding a catch-all route at the end of your router:
App.Router.map(function() {
this.resource('post', ...);
this.resource('user', ...);
this.route('catchAll', { path: '/*' });
});
App.CatchAllRoute = ...
App.Router.map(function() {
//set up all of your known routes, and then...
this.route("fourOhFour", { path: "*path"});
});
.. where you have your FourOhFourRoute defined to show the "no route found" message of your choosing. You will be able to access the originally requested path in the fourOhFour route as the path parameter.
EDIT: just for clarity -- this answer came after the others were reported not to work anymore.
EDIT 2: I've updated the answer to reflect Yehuda Katz's comment (if I have it wrong, please LMK).
Solution 1
To display 404 content:
App.Router.reopen({
handleURL: function (url) {
try {
return this._super(url);
} catch (error) {
if (error.message.match(/No route matched the URL/)) {
return this._super('/404');
}
}
}
});
If you want to URL changes to 404 as well:
App.Router.reopen({
location: locationImplementation,
handleURL: function (url) {
try {
return this._super(url);
} catch (error) {
if (error.message.match(/No route matched the URL/)) {
this.transitionTo('404');
return this._super('/404');
}
}
}
});
To understand what happened here see line 22636
in ember rc2.
Solution 2
Parse current URL and check if route or resource exist using App.Router.router.recognizer.hasRoute('route.path.goes.here');
Here is an example:
I define the last route in my router using a wildcard route see: http://emberjs.com/guides/routing/defining-your-routes/#toc_wildcard-globbing-routes
I have a /not-found
route, see last route defined in my router /*path
to catch any text string, see: https://github.com/pixelhandler/blog/blob/master/client/app/router.js#L19
Router.map(function () {
this.route('about');
this.resource('posts', function () {
this.resource('post', { path: ':post_slug' });
});
this.resource('admin', function () {
this.route('create');
this.route('edit', { path: ':edit_id' });
});
this.route('not-found', { path: '/*path' });
});
That route does a redirect to /not-found
, see: https://github.com/pixelhandler/blog/blob/master/client/app/routes/not-found.js
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');
}
}
});
Also 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.
actions: {
error: function (error) {
Ember.Logger.error(error);
this.transitionTo('/not-found');
}
}
Which renders a not-found
template, see: https://github.com/pixelhandler/blog/blob/master/client/app/templates/not-found.hbs
<h1>404 Not Found</h1>
<p>
Perhaps you have a link that has changed, see {{#link-to 'posts'}}Archives{{/link-to}}.
</p>
Here is my 404 page: http://pixelhandler.com/not-found