Params inheritance strategy with Angular Router
Params inheritance strategy with Angular Router
Few weeks ago I discussed about Angular router, how we could make sure our data are loaded before accessing a component. If you aren’t familiar with Angular router, I suggest you have a look at my previous blog post where I introduced the router.
The example was loading data from the store (ngrx store) to check if data were loaded.
But it would have been difficult if we needed to load data from the route params. Today we will see the problem faced when taking params from the route and how it can be resolve with a newly introduced feature in Angular router since 5.2.x.
1. Getting data from the route params
2. paramsInheritanceStrategy
1. Getting data from the route params
To get data from the route params we take can use the ActivatedRouteSnapshot
or the .snapshot
property of the ActivatedRoute
and use the .params
property. Suppose that we have a route /test/:myKey
, and we navigate to /test/hello
, we could do the following:
const key = route.params['myKey'];
console.log(key);
// prints hello
That worked fine because the activated route was /test/:myKey
which displayed the component. But if you register a child route for example /test/:myKey/test
, and try to access myKey
from the component, you will get undefined
.
// in the router
{
path: 'test/:myKey',
component: MyComponent,
children: [{
path: 'test',
component: MySecondComponent
}]
}
// in my second component
const key = route.params['myKey'];
// key is undefined
The reason why myKey
is undefined is that the activated route is the child route and by default params and data are localized to the route itself. Therefore myKey
is only accessible from MyComponent
through the params.
There are exceptions where params and data are inherited, it happens for empty routes and componentless routes.
Otherwise From a child route, it can be accessed with the .parent
property which gives access to the parent route of the current route.
// in my second component
const key = route.parent.params['myKey'];
The main problem of accessing the route through the parent property is that the component becomes coupled with its position in the route hierarchy. If we change the position of the child route, for example we place it one level under, we would need to chain the code.
{
path: 'test/:myKey',
component: MyComponent,
children: [{
path: 'hello',
component: MyHelloComponent,
children: [{
path: 'test',
component: MySecondComponent
}]
}]
}
We will only be able to get myKey
from the following:
const key = route.parent.parent.params['myKey'];
This is an issue as the route placement should be independed to the component code. Lucky us, Angular deployed a new functionality of the route available in 5.2.x onward.
2. paramsInheritanceStrategy
Since Angular 5.2.x, the router now has a new option paramsInheritanceStrategy
.
RouterModule.forRoot(routes, {
paramsInheritanceStrategy: 'always'
})
By default, the params and data are only inherited for empty route or componentless routes otherwise they are localised as we saw in 1). The problem with that is that the component code becomes coupled with the position in the route.
To allow all params and data to be passed down to the child route, we can set the paramsInheritanceStrategy
to always
.
By setting the inheritance strategy to always, myKey
will then be available in the params regardless of the position of the component in the child components hierarchy. Not just myKey
but any data or params added by parents will be concatenated together and passed down.
Only one problem is that overlapping values will be overwritten by the current activated route values.
{
path: 'test/:myKey',
component: MyComponent,
data: {
bye: "Bye"
},
children: [{
path: 'hello',
component: MyHelloComponent,
children: [{
path: 'test',
component: MySecondComponent,
data: {
bye: "Hello"
},
}]
}]
}
For example here bye
value in MyHelloComponent
will be Bye
while in MySecondComponent
, it will be Hello
. It is overwritten by the current activated route.
Conclusion
Params and data in Angular Router are very important to initialize a component based on the route access by the user. Few days ago Angular released a new feature of the router called paramsInheritanceStrategy
. Params inheritance strategy can be used to allow inheritance of all params and data for child routes. In this post we drafted the problem and saw how paramsInheritanceStrategy
is used to solve the problem of accessing params and data from child route components. Hope you like this post, see you next time!
Excellent description. You just solved one heck of an issue. A million thanks.
ReplyDelete