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

196 Views Asked by At

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?

1

There are 1 best solutions below

0
mumenthalers On BEST ANSWER

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 :)