【问题标题】:Angular: how to call router.navigate() relative to target route in a RouteGuard?Angular:如何在RouteGuard中相对于目标路由调用router.navigate()?
【发布时间】:2018-09-23 04:43:48
【问题描述】:

我有一个使用 Angular 4 开发的现有项目。我需要根据用户权限控制对特定路由的访问。简化的路由配置如下所示:

[
    { path: '', redirectTo: '/myApp/home(secondary:xyz)', pathMatch: 'full' },
    { path: 'myApp'
      children: [
        { path: '', redirectTo: 'home', pathMatch: 'full' },
        { path: 'home', ... },
        ...
        { path: 'product'
          children: [
            { path: '', redirectTo: 'categoryA', pathMatch: 'full' },
            { path: 'categoryA', component: CategoryAComponent, canActivate: [CategoryACanActivateGuard]},
            { path: 'categoryB', component: CategoryBComponent},
            ...
          ]
        },
        ...
      ]
    },
    ...
]

现在,我想控制对www.myWeb.com/myApp/product/categoryA 的访问。如果用户没有足够的权限,他/她将被重定向到... /product/CategoryB。我写了一个CanActivate RouteGuard 来做这个,守卫类看起来像这样:

import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot, ActivatedRoute } from '@angular/router';
import { MyService } from '... my-service.service';

@Injectable()
export class CategoryACanActivateGuard implements CanActivate {
    constructor(private myService: MyService, private router: Router) { }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
        return this.myService.checkPermission()
            .then(result => {
                if (!result.hasAccess) {
                    //redirect here

                    this.router.navigate(['./myApp/product/categoryB']); 
                    //works, but I want to remove hardcoding 'myApp'

                    //this.router.navigate(['../../categoryB']);
                    //doesn't work, redirects to home page

                    //this.router.navigate(['./categoryB'], { relativeTo: this.route});
                    //do not have this.route object. Injecting Activated route in the constructor did not solve the problem

                }
                return result.hasAccess;
            });
    }
}

一切正常,但我希望相对于目标路由进行重定向,如下所示:

this.router.navigate(['/product/categoryB'], { relativeTo: <route-of-categoryA>});
// or 
this.router.navigate(['/categoryB'], { relativeTo: <route-of-categoryA>});

不幸的是,relativeTo 只接受ActivatedRoute 对象,而我只有ActivatedRouteSnapshotRouterStateSnapshot。有没有办法相对于目标路线进行导航(在本例中为 categoryA)?任何帮助将不胜感激。

注意:

  • 除了添加一些路由保护之外,我无法更改路由配置。
  • 我不是使用state.url 寻找this.router.navigateByUrl。我想使用router.navigate([...], { relativeTo: this-is-what-need})

【问题讨论】:

    标签: angular angular-routing angular-route-guards


    【解决方案1】:

    事实证明,注入 ActivatedRoute 的构造函数在 RouteGuard 中的工作方式与 Component 等其他地方不同。

    在组件中,ActivatedRoute 对象指向激活该组件的路由。例如,在CategoryAComponent 类中,以下代码将导航到CategoryB

    this.router.navigate([ '../CategoryB' ], { relativeTo: this.route });
    

    但是,上面的相同代码在添加到 CategoryA 路由配置的 RouteGuard 类中不起作用。在我的测试中,我发现注入ActivatedRoute对象的构造函数指向根路由。另一方面,ActivatedRouteSnapshot 对象(在 canActivate 函数中作为参数传入)指向目标路由(在我的例子中为 categoryA)。但是,我们不能在this.router.navigate(...) 函数中传递这个ActivatedRouteSnapshot 对象。

    我找不到更好的方法来解决这个问题,但以下代码对我有用:

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
        return this.myService.checkPermission()
            .then(result => {
                if (!result.hasAccess) {
                    //redirect here
    
                    let redirectTo = route.pathFromRoot
                        .filter(p => p !== route && p.url !== null && p.url.length > 0)
                        .reduce((arr, p) => arr.concat(p.url.map(u => u.path)), new Array<string>());
    
                    this.router.navigate(redirectTo.concat('categoryB'), { relativeTo: this.route });
                }
                return result.hasAccess;
            });
    }
    

    【讨论】:

    • 有同样的问题。这个解决方案很麻烦,但它有效!谢谢。
    猜你喜欢
    • 2019-03-10
    • 2019-08-15
    • 1970-01-01
    • 1970-01-01
    • 2020-08-04
    • 1970-01-01
    • 2017-12-14
    • 2018-02-13
    • 1970-01-01
    相关资源
    最近更新 更多