The otherwise()
part catches paths that do not match to any of the specified routes.
In your case, the route matches, but the template is not available at the specified URL.
$routeProvider
doesn't know anything about it and can't do much either.
What you can do, is somehow (see below) check if the template is available and if it is not use $location
to redirect to an appropriate path (e.g. /error/404
).
In order to determine if the page is valid (i.e. its template is available) you could try to access the template (using $http
) and catch any errors (indicating there is no template) etc. But I don't like this approach (as relying on a the availability of a template for determining the page's existence/validity isn't a very good practise imo - e.g. it could easily lead to misleading error messages in case of a network or server problem etc).
My favorite approach is to keep a list of "valid"/existing pages and check against it. If the current page should be available, proceed as usual to fetch the template etc. If not, redirect to an error page.
The logic described above could be placed in $routeProvider
's resolve
property (so it gets executed before the controller is instantiated and the view loaded).
E.g.:
var app = angular.module(...);
// This should be a constant, so it can
// get injected into configuration blocks
app.constant('EXISTING_PAGES', [
'page1',
'page2',
...
]);
app.config(function configRouteProvider($routeProvider, EXISTING_PAGES) {
$routeProvider.
when('/', {
templateUrl: 'views/dashboard.html'
}).
when('/:page', {
templateUrl: function getPageTemplateUrl(routeParams) {
return 'views/' + routeParams.page + '.html';
},
resolve: {
exists: function resolveExists($location, $route) {
// Because this is executed before the instantiation of the
// controller and the view is not fully loaded yet, the parameters
// should be accessed via `$route.current.params`
if (EXISTING_PAGES.indexOf($route.current.params.page) === -1) {
// This is not a valid/existing page,
// let's redirect to an appropriate error page
$location.replace(); // Replace the URL in the history
$location.path('/error/404');
}
return true;
}
}
}).
// This should be a separate route, so we can redirect to it
when('/error/404', {
templateUrl: '404.html'
}).
otherwise({
redirectTo: '/error/404'
});
});
See, also, this short demo.