Given a URL, e.g. /path/path2/path3/123;sdf=df
and a routes configuration:
{ path: 'path', data: { g: 'h' }, children: [
{ path: 'path2', data: { c: 'd' }, children: [
{ path: 'something', component: TestpageComponent, data: { a: 'b' } },
{ path: 'path3/create', component: TestpageComponent, data: { b: 'c' } },
{ path: 'path3/:id', component: TestpageComponent, data: { b: 'c' } },
] }
] },
What I need is to find an actual configuration for all the segments in order to get a result set of all data
parameters on all levels (each segment of the url).
I can split the URL in the segments by e.g.
console.log(this.router.parseUrl(url));
or to be more precise
console.log(this.router.parseUrl(url).root.children['primary'].segments);
which will return
[{"path":"path","parameters":{}},{"path":"path2","parameters":{}},{"path":"and","parameters":{}},{"path":"123","parameters":{"sdf":"df"}}]
So, splitting the URL into segments is not a problem. However I need to get a configuration for each segment.
I can get the actual configuration for all the routes with
console.log(this.router.config);
I can go with the segments through the configuration tree and find out the branch I need, but it can cause troubles e.g. while resolving :id
against create
segment. So, I would like to use the router's way of resolving the configuration that if the inner router implementation changes I would not need to change mine.
Example: imagine I have a 50% of the URLs protected by some guard (e.g. only logged in users could go there) and other 50% is not protected (displayed for everybody). So, on the navigation menu level (outside of the router-outlet
) I want to display only the links which are relevant for the current user, so I need to know which routes are protected by the guard. Guards / data / whatever is just a particular case of the problem.
Please do not stick to the example, I am searching for a common way to get the configuration set for a particular URL.
Is this anyhow possible?
With version 2.x you can use the recognize
function the router internally uses to match an url to a RouteStateSnapshot
.
import { recognize } from '@angular/router/src/recognize';
recognize(null, this.router.config, this.router.parseUrl(url), url).subscribe(route => {
var routeSnapshot = route.root.firstChild;
// Go to all children to get actual route.
// If you use routes with children you should have
// the full tree here
var childSnapshot = routeSnapshot.firstChild;
while (childSnapshot != null) {
childSnapshot = routeSnapshot.firstChild;
if (childSnapshot != null) {
routeSnapshot = childSnapshot;
}
}
let routeData = routeSnapshot.data || {};
// routeData['a']...
});
Sadly this seems to no longer work with version 4.x. For version 4.x i've created a pull request to add a new method to the Router
to expose the recognize function.
https://github.com/angular/angular/issues/15826
Another side note. it makes sense to also handle errors of the promise (either of the recognize or the new router method), by adding .catch((rej) => { // some code if it fails to resolve route })
. It can happen that it fails to resolve the url->routestatesnapshot. Either because the url is wrong or you use async routes via LoadChildren
and the routes are not yet loaded. Breadcrumbs work great using this even with async routes. If you use it to check permissions, for example via a directive, you need to watch out if you use async routes.