How to elegantly get full url from the ActivatedRo

2020-07-02 08:04发布

问题:

In some of my Angular route guards, I want to set up the "next" path, to redirect to after successful login.

So, the ordinary guard canActivate function signature looks like this:

public canActivate(route: ActivatedRouteSnapshot): Observable<boolean> | boolean {
  // ...blah
  return true;
}

The route parameter is an instance of ActivatedRouteSnapshot.

Previously to get the "next" URL I was just getting it from the route.url. This works just fine, as long as there are no children routes.

My example URL is /search/advanced?query_hash=1221d3b57f5616ee16ce70fdc78907ab, where advanced is a child route of a search.

Child routes can be found in route.children, but iterating over these children (especially there might be multiple levels) and combining the URL this way seems awkward and ugly.

What I'm interested in is contained in route._routerState.url property (being a string, on the bottom of the image below), but it's a "private" variable.

Am I missing something? How can one elegantly get the full (with children paths) URL from the ActivatedRouteSnapshot? Angular version is 5.1.

回答1:

There's no ready to use function from Angular router to achieve that, so I wrote them:

function getResolvedUrl(route: ActivatedRouteSnapshot): string {
    return route.pathFromRoot
        .map(v => v.url.map(segment => segment.toString()).join('/'))
        .join('/');
}

function getConfiguredUrl(route: ActivatedRouteSnapshot): string {
    return '/' + route.pathFromRoot
        .filter(v => v.routeConfig)
        .map(v => v.routeConfig!.path)
        .join('/');
}

Example output when route is from ProjectComponent:

const routes: Routes = [
    {
        path: 'project', component: ProjectListComponent, children: [
            {path: ':id', component: ProjectComponent}
        ]
    },
];
getResolvedUrl(route) => /project/id1
getConfiguredUrl(route) => /project/:id


回答2:

try this to get it from RouterStateSnapshot

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
      console.log(state.url)
      ...