如何访问Guard中正在测试的当前Url Segment

问题描述 投票:0回答:1

我有一个 generic

CanActivate
守卫,想改变相应路径段(被测试的那个)的矩阵参数。

使用给定的路由配置:

{
  path: 'parent',
  canActivate: [ensureSortMatrixParamsGuard],
  children: [
    { path: 'child', component: ChildComponent },
  ]
}

还有

CanActivate
守卫:

const ensureSortMatrixParamsGuard: CanActivateFn = (route, state) => {
  if (!route.paramMap.has('sort')) {
    const tree = // TODO -> should be `/parent;sort=asc
    return tree
  }
  return true
}

如何在守卫中创建一个

UrlTree
以确保相应路径段(添加守卫的那个,=
sort
)上的
/parent
矩阵参数?

使用以下解决方案,我可以以某种方式访问 url 段,但只能以一种非常 hacky 的方式 - 相应的段并不总是最后一个(仅当直接访问路由时,而不是其子项之一)。

const tree = inject(Router).parseUrl(state.url)
const primarySegments = tree.root.children[PRIMARY_OUTLET].segments
const lastPrimarySegment = primarySegments[primarySegments.length - 1]

// then add the matrix param and then return the `tree`
lastPrimarySegment.parameters['sort'] = 'asc'

我怎么能断定

UrlTree
的哪一段对应于
RouteSnapshot


更新

我找到了一个似乎有效的方法:

/**
 * returns all the parent ARS and provided ARS in an array
 * e.g. [ars.parent.parent, ars.parent, ars]
 */
function anchestorRouteSnapshots(ars: ActivatedRouteSnapshot | null): ActivatedRouteSnapshot[] {
  return ars ? [...anchestorRouteSnapshots(ars.parent), ars] : []
}

const anchestors = anchestorRouteSnapshots(route)
        .map((ars) => ars.routeConfig)
        .filter((rc) => !!rc && rc.path !== '') // there might be ARS without routeConfig (e.g. AppRoot) or with an empty path part

// this is the segment from the UrlTree I want to add the matrix param
const segment = primarySegments[anchestors.length - 1]

我创建了一个Stackblitz:)

angular angular-router guard canactivate
1个回答
0
投票

你能试试这段代码并让我知道错误吗?

        { Injectable } from '@angular/core';
    import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, CanActivateFn, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
    
    @Injectable({
      providedIn: 'root'
    })
    export class EnsureSortMatrixParamsGuard implements CanActivate, CanActivateChild {
      constructor(private router: Router) {}
    
      canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree {
        return this.ensureSortMatrixParams(route, state);
      }
    
      canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree {
        return this.ensureSortMatrixParams(childRoute, state);
      }
    
      private ensureSortMatrixParams(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree {
        if (!route.paramMap.has('sort')) {
          const segments = this.getSegmentsForRoute(route, state);
          segments[segments.length - 1].parameters['sort'] = 'asc';
          const tree = this.router.createUrlTree([], { queryParamsHandling: 'preserve', fragment: state.fragment, queryParams: state.queryParams });
          tree.root.children[0].segments = segments;
          return tree;
        }
        return true;
      }
    
      private getSegmentsForRoute(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): any[] {
        const url = this.router.createUrlTree([], {relativeTo: route, queryParamsHandling: 'merge'}).toString();
        const tree = this.router.parseUrl(url);
        const primarySegments = tree.root.children[0].segments;
        const ancestorRouteSnapshots = this.getAncestorRouteSnapshots(route);
        const matchingSegmentIndex = this.getMatchingSegmentIndex(primarySegments, ancestorRouteSnapshots);
        return primarySegments.slice(0, matchingSegmentIndex + 1);
      }
    
      private getAncestorRouteSnapshots(route: ActivatedRouteSnapshot): ActivatedRouteSnapshot[] {
        const snapshots = [];
        while (route.parent) {
          snapshots.push(route.parent);
          route = route.parent;
        }
        return snapshots.reverse();
      }
    
      private getMatchingSegmentIndex(primarySegments: any[], ancestorRouteSnapshots: ActivatedRouteSnapshot[]): number {
        let matchingSegmentIndex = -1;
        for (let i = 0; i < ancestorRouteSnapshots.length; i++) {
          const routeConfig = ancestorRouteSnapshots[i].routeConfig;
          if (routeConfig && routeConfig.path) {
            const matchingSegment = primarySegments.find(segment => segment.path === routeConfig.path);
            if (matchingSegment) {
              matchingSegmentIndex = primarySegments.indexOf(matchingSegment);
            }
          }
        }
        return matchingSegmentIndex;
      }
    }
© www.soinside.com 2019 - 2024. All rights reserved.