Skip to content

bug: relative navigation doesn't work inside route guards #22763

Closed

Description

@jorroll

I'm submitting a...


[x] Bug report  

Current behavior

Inside a route guard, injecting ActivatedRoute and attempting relative navigation via this.router.navigate(['../sibling'], {relativeTo: this.route}) results in a Error: Cannot match any routes. URL Segment: 'sibling'

Expected behavior

Relative navigation should work normally

Minimal reproduction of the problem with instructions

A stackblitz example of the issue can be seen here: https://stackblitz.com/edit/angular-gitter-k7fjds

What is the motivation / use case for changing the behavior?

  1. This appears to be a bug
  2. If a user navigates to a child route and includes a specific queryParam, I'd like to redirect the user to a sibling route. Currently, this does not appear to be possible inside a route guard with relative navigation.

Additional Information

It appears that the ActivatedRoute injected into a route guard is always an instance of the root route. Inside a route guard, this.router.navigate(['.'], {relativeTo: this.route}) always takes the user back to the root route, rather than navigating them to the same route they are currently on.

Environment


Angular version: 5.0.0


Browser:
- [x] Chrome (desktop) version 64

Activity

  1. mantuonweb commented on Apr 26, 2019

    @mantuonweb

    Yes , I did but may be this fixed in updated one.
    Just wants to know that

  2. MarcusRiemer commented on Feb 25, 2020

    @MarcusRiemer

    It really is a pity that this is so hard. Another workaround was mentioned in #28682, but this also doesn't seem to work anymore with Angular 9:

    return (this.router.parseUrl(`${state.url}/../unknown`));
    

    For me the "expected" solution would be to accept a RouterStateSnapshot in Router.createUrlTree. From what I can tell snapshot property is the only thing from the route that is used anyway:

    function findStartingPosition(nav: Navigation, tree: UrlTree, route: ActivatedRoute): Position {
    if (nav.isAbsolute) {
    return new Position(tree.root, true, 0);
    }
    if (route.snapshot._lastPathIndex === -1) {
    return new Position(route.snapshot._urlSegment, true, 0);
    }
    const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
    const index = route.snapshot._lastPathIndex + modifier;
    return createPositionApplyingDoubleDots(
    route.snapshot._urlSegment, index, nav.numberOfDoubleDots);
    }

    Called from

    const startingPosition = findStartingPosition(nav, urlTree, route);

    Which in turn is called from https://github.com/angular/angular/blob/9.0.2/packages/router/src/router.ts#L951

    @jasonaden (or anyone from the Angular team): This seems like a trivial fix, so I guess im am overlooking something?

  3. NLueg commented on Mar 12, 2020

    @NLueg

    Still having this Issue in Angular 9 ... It's a pity, that there is no priority in fixing this.

  4. added
    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
    and removed
    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
    on Oct 1, 2020
  5. modified the milestones: Backlog, needsTriage on Oct 1, 2020
  6. added
    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
    on Oct 1, 2020
  7. modified the milestones: needsTriage, Backlog on Oct 1, 2020
  8. ddralves commented on Nov 17, 2020

    @ddralves

    Any update on this issue?

  9. sergiypayu commented on Feb 15, 2022

    @sergiypayu

    Here is my workaround:

        canActivate(route: ActivatedRouteSnapshot): UrlTree | boolean {
                // construct full url from urlSegments descending from root
                const urlSegments = route.pathFromRoot
                    .map((snapshot) => snapshot.url)
                    .reduce((acc, urlSegments) => acc.concat(urlSegments), [])
                    .filter((urlSegment) => !!urlSegment);
                const currentUrl = urlSegments.map((urlSegment) => urlSegment.path);
                const relativeUrl = currentUrl.concat(['page']);
                return this.router.createUrlTree(relativeUrl);
        }
    
  10. atscott commented on Apr 22, 2022

    @atscott
    Contributor

    The TL;DR for this one is that this is something I would absolutely love to do but will be a breaking change to update router.createUrlTree to do it.

    The implementation for creating a URL tree is really confusing and actually requires that the ActivatedRoute/ActivatedRouteSnapshot be part of the current router url. In reality, we should really be able to create a url from any ActivatedRouteSnapshot, but that requires the shape of the ActivatedRoute/ActivatedRouteSnapshot to be valid (which is commonly not the case in tests due to stubbing this out).

    There is maybe an opportunity to introduce this new way of creating the URL as a standalone function exported as public API in the router and then later making the breaking change to include it in router.createUrlTree. This would be problematic for discovery and documentation but would at least provide an early opt-in for anyone trying to do this.

  11. angular-automatic-lock-bot commented on Jun 24, 2022

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  12. locked and limited conversation to collaborators on Jun 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions