How to defer routes definition in Angular.js?
Since routes are defined on a provider level, normally new routes can only be defined in the configuration block. The trouble is that in the configuration block all the vital services are still undefined (most notably $http
). So, on the surface it looks like w can't define routes dynamically.
Now, it turns out that in practice it is quite easy to add / remove routes at any point of the application life-cycle! Looking at the $route
source code we can see that all the routes definition are simply kept in the $route.routes
hash which can be modified at any point in time like so (simplified example):
myApp.controller('MyCtrl', function($scope, $route) {
$scope.defineRoute = function() {
$route.routes['/dynamic'] = {templateUrl: 'dynamic.tpl.html'};
};
});
Here is the jsFiddle that demonstrates this in action: http://jsfiddle.net/4zwdf/6/
In reality, if we want to be close to what AngularJS is doing the route definition logic should be a bit more complex as AngularJS is also defining a redirect route to correctly handle routes with /
at the end (make it effectively optional).
So, while the above technique will work, we need to note the following:
- This technique depends on the internal implementation and might break if the AngularJS team decides to change the way routes are defined / matched.
- It is also possible to define the
otherwise
route using the$route.routes
as the default route is stored in the same hash under thenull
key
I found that the answer by @pkozlowski.opensource works only in angularjs 1.0.1. However, after angular-route.js becomes an independent file in the later version, directly set the $route doesn't work.
After reviewing the code, I find the key of $route.routes is no longer used to match location but $route.route[key].RegExp is used instead. After I copy the origin when and pathRegExp function, route works. See jsfiddle: http://jsfiddle.net/5FUQa/1/
function addRoute(path, route) {
//slightly modified 'when' function in angular-route.js
}
addRoute('/dynamic', {
templateUrl: 'dynamic.tpl.html'
});