Skip to content

Angular 10 changes router outlet url so site cannot be reloaded in browser聽#39401

Closed

Description

@anthonn

馃悶 bug report

Affected Package

The issue is probably caused by package @angular/router

Is this a regression?

Yes, the previous version in which this bug was not present was: Angular 9 (9.1.12)

Description

In angular 9 if using router navigation like:
this.router.navigate(["parent", { outlets: { primary: "child" } }], {});

It will produce the following url: /parent/(child)
but in angular 10 this url will instead be: /parent/child

They will though have the same currentUrlTree structure in the angular router in both angular 9 and 10 if the navigation was made with the angular router.

But if the browser is reloaded or the url (with /parent/child) are pasted into another browser window the internal UrlTree of the angular router will have a different structure.

So in angular 10 the urlTree has one structure if using: this.router.navigate(["parent", { outlets: { primary: "child" } }], {});
but if reloading the browser from that specific url the initial created url tree will have a different structure. See the provided stackblitz console for more details.

Before reload:
image

After:
image

This issue then in its turn blocks the possibility to activate a named outlet for the router.

馃敩 Minimal Reproduction

Example with Angular 9: https://stackblitz.com/edit/angular-sdc5rh?file=src/app/parent/parent.component.ts
Example with Angular 10: https://stackblitz.com/edit/angular-jqkm4x?file=src/app/parent/parent.component.ts

Check the different behavior between angular 9 and 10 by pressing:

  1. Show parent
  2. Show child by router navigate
  3. Reload window
  4. Show child-named-outlet

Step 4 only works in angular 9

Press the "Show Parent" to "reset the application" and test other combinations if needed.
Also check the console that logs the different UrlTree structures

Activity

  1. added this to the needsTriage milestone on Oct 23, 2020
  2. atscott commented on Oct 26, 2020

    @atscott
    Contributor

    The url generated in v10 for this.router.navigate(["parent", { outlets: { primary: "child" } }], {}); is correct and should be /parent/(child) rather than /parent/child -- no secondary outlets are active and every segment in the URL is part of the primary outlet.

    When navigating from this url, the behavior is broken in both v9 and v10 isn't a regression in that respect but does put your application in an awkward position

    The broken navigation from /parent/child to /parent/(child//secondOutlet:child-named-outlet) duplicate of #13523

    As a workaround, you should be able to change your navigation to:

        this.router.navigate(
          [".", { outlets: { secondOutlet: "child-named-outlet" } }],
          {
            relativeTo: this.activatedRoute
          }
        );
    

    https://stackblitz.com/edit/angular-clrva1?file=src%2Fapp%2Fparent%2Fparent.component.ts

    I think this should work for you and has the benefit of working in each of your scenarios in the example whereas v9 would not work for navigating from /parent/child to the secondary outlet. While it doesn't allows you to navigate directly to 'child' in the primary and 'child-named-outlet' in the secondary at the same time (you couldn't do it in v9 either because of #13523), this does get you back the behavior you had previously. I think the fact that you had to specify "child" in the outlets map in v9 was actually worse because the intent appears to really have been to stay on the same path for the primary outlet rather than navigating to "child".

    Closing as duplicate of #13523

  3. anthonn commented on Oct 27, 2020

    @anthonn
    Author

    Thank you very much for your answer @atscott !

    The workaround works fine. It solves my issue.

    But is it still not wrong that the exact same url (/parent/child) in the browser gives two different structures of the angular router internal UrlTree, depending on how the applications gets to that url?

    If starting at /parent and then navigating by:
    this.router.navigate(["parent", { outlets: { primary: "child" } }], {});
    which results in the "/parent/child" url in the broswer. The UrlTree will look as the first picture above.

    But then if reloading the browser with "/parent/child" url the UrlTree will instead have the structure as the second picture above.

    I am only talking about v10 now.

  4. atscott commented on Oct 27, 2020

    @atscott
    Contributor

    @anthonn - It's weird but I wouldn't necessarily say it's wrong. One might also ask if it's wrong for two different urls (/parent/child vs /parent/(child)) to represent the exact same activated config in the router (behavior in v9). The fact that there are two separate ways to represent the same url internally as a UrlTree doesn't seem like an issue. I think ultimately v10 is in a better state, at least moving towards fewer ways to represent the same thing via a consistent URL.

    Side note: I did pinpoint the issue that prevented your navigation from working:

    this.router.navigate(
          [{ outlets: { primary: "child", secondOutlet: "child-named-outlet" } }],
          {
            relativeTo: this.activatedRoute
          }
        );
    

    When the primary route was used in the outlets list along with relativeTo or some series of commands before the outlets map, all other outlets were ignored. I should have a fix for that particular issue soon.

  5. anthonn commented on Oct 27, 2020

    @anthonn
    Author

    I do agree that with the (/parent/child vs /parent/(child)) representing the same config in v9.

    But if typing /parent/(child) in v10, angular will change to /parent/child by itself, but will have a different state (UrlTree) compared to if /parent/child was entered from the beginning.

    Well it works for me now so I do not need any other changes if its not needed, just for info.

    Anyhow, thanks again @atscott !

  6. angular-automatic-lock-bot commented on Nov 27, 2020

    @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.

  7. locked and limited conversation to collaborators on Nov 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions