'Angular CanActivate guard - createUrlTree relative navigation
I currently have a route guard such as
export class EntityGuard implements CanActivate {
constructor(private readonly router: Router, ...) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean | UrlTree> {
...
This guard is activated for the URL
basePath/select/10/123
which means
basePath/select/:type/:id
When a certain condition is met, I need to force navigation back to
basePath/select/:type
How can I do that using createUrlTree? E.g.
if (...) {
return of(this.router.createUrlTree([../', type]));
}
I'd need to set the
{ relativeTo: parent }
option. However I can't seem to find a way to do it.
My current solution is
private navigateBack(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const end = state.url.indexOf(route.url[route.url.length - 1].path);
const parentUrl = state.url.slice(0, end);
return of(this.router.createUrlTree([parentUrl]));
}
Which I really don't like. String manipulation is big no for me.
Solution 1:[1]
I have a workaround to get the URL Segment for current route:
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
): boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {
const currentUrlFragments = route.pathFromRoot.flatMap((s) => s?.url ?? []).map((s) => s.path);
return this.router.createUrlTree([...currentUrlFragments, '../']);
}
}
Solution 2:[2]
There is one more workaround getting the url from Router like this this.router.getCurrentNavigation()?.extractedUrl.toString()
Full example below:
@Injectable({
providedIn: 'root',
})
export class MyGuard implements CanActivate, CanLoad {
constructor(private router: Router) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
):
| Observable<boolean | UrlTree>
| Promise<boolean | UrlTree>
| boolean
| UrlTree {
return this.redirect();
}
canLoad(
route: Route,
segments: UrlSegment[]
):
| Observable<boolean | UrlTree>
| Promise<boolean | UrlTree>
| boolean
| UrlTree {
return this.redirect();
}
private redirect() {
let url = this.router.getCurrentNavigation()?.extractedUrl.toString() || '/';
return this.router.createUrlTree([url, 'other', 'relative','path']);
}
}
Guarding a path like hello/:name with the above guard would result navigating to hello/:name/other/relative/path, e.g. hello/world/other/relative/path.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Nicolas |
| Solution 2 |
