The problem we want to resolve:
- in top level router, we have user page defined as
{route: "user/:id",...}
. - in user page, we build 2nd level child router. We want to show different routes for different user type, for instance, show “admin” tab for admin user.
We have a problem here. The “User” component configureRouter()
is processed before canActivate/activate(params)
callbacks. This means you don’t know the user id when building the routes table in configureRouter(...)
.
The best you can do so far, is to mutate routes table afterwards in activate
or canActivate
callback. While it gets the job done, it has two issues:
- the navigation tabs flick because the async adding of new admin tab,
- you cannot hit browser “refresh” button while on “/user/1/admin” page, because the original routes table doesn’t know about the “admin” route.
The existing way is not optimal:
export class User() {
activate(params, routerConfig) {
this.id = params.id;
return ajaxToGetUser(this.id).then(user => {
if (user.isAdmin) {
this.router.addRoute({
route: 'admin', name: 'admin', title: 'Admin',
nav: true, moduleId: './user/admin'
});
this.router.refreshNavigation();
}
});
}
configureRouter(config, router) {
this.router = router;
config.map([
{
route: '', name: 'details', title: 'Details',
nav: true, moduleId: './user/details'
}
]);
}
}
Well, it turns out we can do it much easier. While reading the aurelia-router source code, I found this undocumented feature of child router.
The child router configureRouter(...)
actually gets extra arguments passed in from navigationInstruction, the first of those extra arguments is the params
of parent route!
This means you can do this, no more flick or page refresh issue:
export class User() {
configureRouter(config, router, params) {
this.router = router;
this.id = params.id;
return ajaxToGetUser(this.id).then(user => {
let routes = [
{
route: '', name: 'details', title: 'Details',
nav: true, moduleId: './user/details'
}
];
if (user.isAdmin) {
routes.push({
route: 'admin', name: 'admin', title: 'Admin',
nav: true, moduleId: './user/admin'
});
}
config.map(routes);
});
}
}
In addition, now you have user
instance while build the routes table, which means you can put it in settings on all sub-routes if you want {route: '', settings: {user}, ...}
.