angular: Router links in `@defer` blocks not having correct relative route

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

17.2.1

Description

A RouterLink with a route of ./ should route to the activated route. (eg. <a [routerLink]="'./'" >Link One</a>). But when it is in a defer block, and it is a sibling of a component that imports from material it routes to the app root. So @defer(on timer(1000)) { <has-material/> <a [routerLink]="'./'" >Link One</a> } routes to the root.

image

Reproduction

StackBlitz link: https://stackblitz.com/edit/stackblitz-starters-prh2zk Steps to reproduce:

  1. Have a RouterLink in a defer block that has a relative route
  2. Give it a sibling that imports from Material

Expected Behavior

The router link route should be relative to the current route.

Actual Behavior

The router link route is from the root. The ‘ActiveRoute’ seems to be incorrect.

Environment

  • Angular: >= 17.2.4
  • CDK/Material: 17.2.2
  • Browser(s): edge, chrome
  • Operating System (e.g. Windows, macOS, Ubuntu): Windows

About this issue

  • Original URL
  • State: closed
  • Created 4 months ago
  • Reactions: 4
  • Comments: 23 (9 by maintainers)

Commits related to this issue

Most upvoted comments

Hello @AndrewKushnir, thanks a lot for the fix. I can confirm on my side that it is working now!

@Yberion @bboyle thanks for providing a repro. We’ve identified the root cause and I’ve created a PR with a fix: https://github.com/angular/angular/pull/55374. I will update this thread once the mentioned PR lands.

@bboyle @atscott We just rolled out with 17.3 and we are having a similar issue. Sometimes the route is ‘stuck’ on an old value. I am also struggling to figure out what causes that behavior and how to reproduce.

FYI, the fix from PR https://github.com/angular/angular/pull/55374 was merged and released as a part of v17.3.6. Please let us know if the problem still exists after updating to v17.3.6.

This bug seems like the previous bug. Using a defer block around a component that imports ‘something’ causes issues with the ActivatedRoute in that component.

Hello, it seems that I have the same problem there, I wanted to use defer blocks to load a different layout depending on the result of the BreakpointObserver, both having a router outlet for child pages.

The problem occur with a component from Angular Material, it seems that the router and ActivatedRoute are not “synchronized” anymore.

  • https://github.com/Yberion/angular-defer
  • npm i
  • npm run start
  • Open the console (everything is logged in the console)
  • click on go to page1 from home
  • click on page2
  • click on page 1
  • click on home
  • Previous page via browser button
  • click on page2
  • click on home
  • Previous page via browser button

And it is at this point that we get different results from the router and the snapshot.

The problem appears in the component that is defered LoaderComponent, no problem in the SomepageComponent (check console logs).

The problem disappears if I remove MatButtonModule from LoaderComponent OR if I remove the defer block from SomepageComponent.

I’m on Angular 17.3.4

FYI I don’t have RouterModule imported anywhere in my app (standalone component migration was completed). Will keep working on reproducing the issue.

@AndrewKushnir is out of office until next week.

I made the reproduction a bit smaller: https://stackblitz.com/edit/stackblitz-starters-uxf7bm I found that removing the RouterModule imports of the component in the defer block makes it work.

Looks good. Thanks for working on it!

@NachmanBerkowitz thanks for reporting the issue.

We found the origin of the problem and we are working on a fix. There are a couple first PRs created with the necessary refactoring (#54903 and #54907) and we’ll need create a couple more PRs that would fix the issue. There is no exact ETA at this moment, but the final fix would likely be available in one of the 17.3.x releases.

I could narrow it down a bit:

The ActivatedRoute has an undefined route when in a defer block and having a import (whatever import).

repro: https://stackblitz.com/edit/angular-repro-54864

Likely related to the injector construction of @defer.

This seems like either a framework or router issue. Material doesn’t use the router at all. Transferring to the framework repo.