2

Problem: I am trying to access the query params that a route guard is checking, and not the current url snapshot query params.

ActivatedRoute only shows the current route status they are on, and not the one that is in transit. So if I am on page 'app/users/list', the route snapshot is 'app/users/list' when the information is pulled for the canActivatedChild guard, but I am trying to access the link they are going to and not where they are coming from. (which is what Angular is suppose to do; which is the current active snapshot)

Question: How does one access a child's query params route that is in transit that is suppose to be guarded against?

Scenario: I have a user's list table, and each user can either go to a dashboard or a editor screen for completion before entering the dashboard. So when a user clicks on a user from the user list table, the route guard should check to see if the user has had certain properties are not null before proceeding to the dashboard, and if they have some null properties they are directed by the guard to the editor page. The dashboard page is guarded by a canActivatedChild guard that decides if a user's details can be shown in that dashboard based on if they have all of the information available, and if not they are redirected to the editor for completion.

 // The Link
 this.router.navigate(['/dashboard', { id: userId }])


 // The Guard
 @Injectable()
 export class CanShowUserDashboard implements CanActivateChild {

   constructor(
     private _router: Router,
     private _route: ActivatedRoute
   ) {}

   canActivateChild() {
    this._route.queryParams.subscribe((next) => {
       let queryParams = next.id;
       // queryParams is undefined
    })
   }
  }

Goal Getting the query params from the dashboard link, and not the current active user's list page.

Only Solution I got? Was thinking about passing the user into a service, and have the guard access the service to pull the information.

Chris Cooley
  • 125
  • 1
  • 10

2 Answers2

1

The canActivateChild function receives the ActivatedRouteSnapshot of the child route as the first parameter.

export interface CanActivateChild {
    canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean;
}

So you can get the user ID from the childRoute argument.

@Injectable()
export class CanShowUserDashboard implements CanActivateChild {

    canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
         // prints the value of userId
         console.log(childRoute.queryParams['id']);
    }
}
Reactgular
  • 52,335
  • 19
  • 158
  • 208
0

This may happened to you because you tried to navigate to the child route without keeping the actual parameter sain as follows this.router.navigate(['child-one', {id:'childparameter'}],{ relativeTo: this.route });, or from template hyperlink like <a [routerLink]="['child']" [queryParams]="{ id: childparam}" > link-to-child </a> , in both cases the browser would destroy the parent querystring even if the route call is relative to the actual route, to prevent it use:

For the first case : this.router.navigate(['/parent' , { id: this.router.routerState.snapshot._root.children[0].value.url[0].parameters['id'] } ,'child' , {id:this.route.snapshot.queryParams['id']} ]); , it keeps the very first parameter in some treenode of the object router.routerState.snapshot._root, corresponding to the lineage of routing system, until the last figuring parameter.

For the second case : <a [routerLink]="[{id:oldparam},'child']" [queryParams]="{ id: childparam }" > link-to-child </a> or <a [routerLink]="['.', {id:oldparam},'child']" [queryParams]="{ id: childparam }" > link-to-child </a> , where oldparam is a scope variable caught in transition phase between routes, as aforementioned in the first case.

Note that i used _root.children[0] arbitrarily, you can use _root.value.firstChild as well, this would have same output.

see my fiddle here

You don't have to fathom all this just see the function CanActivateChild() that has this.route.queryParams.subcribe part.

decide(a,b){

   if(a.children[0]!==undefined){
      console.log('haschild');
      return a.value.url[0].parameters['id'];}
    else
    {
      console.log('dosnt have child');
      return b;
    }
  }

CanActivateChild () {

    console.log("decide");

    this.route.params.subscribe((next) => {
       console.log("logging parent")
       console.log( this.decide(this.router.routerState.snapshot._root.children[0],next.id));
    });
  }

This function logs the transitive query parameters if the route call is nested, or the last subcribed parameter if the address is childless. Which can be pointed by decide() function.

Abr001am
  • 571
  • 6
  • 19