Angular2 relative route moves to guard

We have descriptions of children's routes in which we use a security guard to check if the user accepted the conditions before using our service.

accounts / secret / secret.routes.ts:

import { Routes } from '@angular/router'; import { SecretFormComponent } from './secret-form.component'; import { SecretTermsComponent } from './secret-terms.component'; import { TermsGuard } from './services/terms-guard.service'; export const secretRoutes: Routes = [ { path: '', redirectTo: 'form' }, { path: 'form', component: SecretFormComponent, canActivate: [TermsGuard] }, { path: 'terms', component: SecretTermsComponent } // otherwise redirect to form { path: '**', redirectTo: 'form' } ]; 

In our terms, we defined this code:

 this.router.navigate(['/account/secret/terms']); return false; 

Is there a way to redirect using relative route navigation from a “routing group”? Because the definition of the absolute path can be violated if one day the toolbar of our account is renamed to something else, for example, to my account. We want our secret module to be reused.

I would like to be able to go to ['./terms'] in my guard, but it does not work, just like the guard does not know where to start relative navigation.

+5
source share
4 answers

router has a url property that contains the current url. you can add from this.

  this.router.navigate([this.router.url,'terms']); 
+1
source

What you want to use is the RouterStateSnapshot parameter of your guard's RouterStateSnapshot method.

RouterStateSnapshot has the current path that you are in the routing process, while Router.url is the current path you are routing from (this is why @ Günter Zöchbauer's answer doesn’t quite work in this scenario).

To make this fully applicable to your use case without additional code, you will want to change your routes to

/account/secret/form and /account/secret/form/terms

 import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router'; import { Observable } from 'rxjs/Observable'; @Injectable() export class ChildRouteGuard implements CanActivate { constructor(private router: Router) { } canActivate(_route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean { if (// user can view the specific route) { return true; } // else route them to a variation of the route this.router.navigate([state.url, 'terms']); return false; } } 

Change 1

You can save your current URL structure by also using ActivatedRouteSnapshot , as shown below

Assuming routes like account/secret/form and account/secret/terms

route.url is an array of URL segments, we want the latter because it will be a form . We find the index of this in the current route, which we are trying to switch to account/secret/form and slice . At this point, we have a “parent” current route to which we are trying to switch to account/secret , and we can add in sibling to the form , which is the terms .

Note: this pattern breaks up when you have duplicate occurrences of form in your URL

 import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router'; import { Observable } from 'rxjs/Observable'; @Injectable() export class ChildRouteGuard implements CanActivate { constructor(private router: Router) { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean { if (// user can view the specific route) { return true; } let parentUrl = state.url .slice(0, state.url.indexOf(route.url[route.url.length - 1].path)); this.router.navigate([parentUrl, 'terms']); return false; } } 
+7
source

You need a current route (e.g. ActivatedRoute ) to create an UrlTree relative to this route. Then you can use this UrlTree with this.router.navigateByUrl(...) :

 let urlTree = this.router.createUrlTree(['./terms'], {relativeTo: this.route}); this.router.navigateByUrl(urlTree); 
0
source

You should be able to get the URL that you were trying to go from state.url, parse it using the provided urlSerializer, and then splicing the new urlSegment you want as to what corresponded to the guard.

 export class TermsGuard implements CanActivate<SecretFormComponent>{ constructor(private router: Router, private urlSerializer: UrlSerializer) { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { let routerStateUrlTree = this.urlSerializer.parse(state.url); let newSegment = new UrlSegment('terms', {}); routerStateUrlTree.root.children.primary.segments.splice(-1, 1, newSegment); this.router.navigateByUrl(routerStateUrlTree); return false; } } 

You said: “I would like to be able to go to ['./terms']”, but based on your routes, I think you meant [' ../terms'], but if you meant [' ./terms'] just change the second splicing parameter to 0 so that it does not delete the last segment.

0
source

Source: https://habr.com/ru/post/1260873/


All Articles