angularangular-routerguardcanactivate

How to access the current Url Segment that is being tested in the Guard


I have a generic CanActivate guard and want to alter the matrix params of the corresponding path segment (the one being tested).

With given route config:

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

And the CanActivate guard:

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

How can I create a UrlTree in the guard which ensures the sort matrix param on the corresponding path segment (the one where the guard was added, =/parent)?

With the following solution I can access the url segment - but only in way that works for the case, when this route is accessed directly (not one of its children; the corresponding segment would not be the last one then).

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'

How can I conclude which segment of the UrlTree corresponds with the RouteSnapshot?


Solution

  • I found a way that seems to work:

    /**
     * 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]
    

    See working Stackblitz :)