Angular 2+:在Transit Query Params中访问路由而不是当前活动路由

时间:2018-06-06 00:20:42

标签: angular angular2-routing angular-guards

问题: 我正在尝试访问路由警卫正在检查的查询参数,而不是当前的url快照查询参数。

ActivatedRoute仅显示他们所在的当前路线状态,而不显示正在传输的状态。因此,如果我在“app / users / list”页面上,当为canActivatedChild警卫拉取信息时,路由快照为“app / users / list”,但我正在尝试访问他们要访问的链接而不是他们来自。 (这是Angular想要做的;这是当前的活动快照)

问题: 如何访问一个孩子的查询参数路由正在传输的路由,以防止被阻止?

方案: 我有一个用户列表,每个用户可以在进入仪表板之前转到仪表板或编辑器屏幕完成。因此,当用户从用户列表中单击用户时,路由防护应检查用户是否在继续执行仪表板之前已将某些属性设置为非空,并且如果他们具有某些空属性,则他们将由警卫指示到编辑页面。仪表板页面由canActivatedChild防护装置保护,该防护装置根据是否具有所有可用信息决定是否可以在该仪表板中显示用户的详细信息,如果不是,则将其重定向到编辑器以完成。

 // 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
    })
   }
  }

目标 从仪表板链接获取查询参数,而不是当前活动用户的列表页面。

我只有解决方案? 正在考虑将用户传递给服务,并让警卫访问服务以获取信息。

2 个答案:

答案 0 :(得分:1)

canActivateChild函数接收子路由的ActivatedRouteSnapshot作为第一个参数。

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

因此,您可以从childRoute参数中获取用户ID。

@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']);
    }
}

答案 1 :(得分:0)

这可能发生在您身上,因为您试图导航到子路由而不保持实际参数sain如下this.router.navigate(['child-one', {id:'childparameter'}],{ relativeTo: this.route });,或者从<a [routerLink]="['child']" [queryParams]="{ id: childparam}" > link-to-child </a>这样的模板超链接导航,在这两种情况下浏览器都会破坏即使路由调用是相对于实际路由的,也是父查询字符串,以防止它使用:

对于第一种情况:this.router.navigate(['/parent' , { id: this.router.routerState.snapshot._root.children[0].value.url[0].parameters['id'] } ,'child' , {id:this.route.snapshot.queryParams['id']} ]);,它保留对象router.routerState.snapshot._root的某个treenode中的第一个参数,对应于路由系统的谱系,直到最后的计算参数。

对于第二种情况:<a [routerLink]="[{id:oldparam},'child']" [queryParams]="{ id: childparam }" > link-to-child </a><a [routerLink]="['.', {id:oldparam},'child']" [queryParams]="{ id: childparam }" > link-to-child </a>,其中oldparam是在路径之间的过渡阶段捕获的范围变量,如第一种情况所述。

请注意,我任意使用_root.children[0],您也可以使用_root.value.firstChild,这将有相同的输出。

see my fiddle here

您无需了解所有这些,只需查看CanActivateChild()部分的this.route.queryParams.subcribe函数。

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));
    });
  }

如果路由调用是嵌套的,则此函数记录传递查询参数;如果地址是无子字符,则记录最后一个子参数。 decide()函数可以指出哪一个。