-
Notifications
You must be signed in to change notification settings - Fork 25.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Router links in @defer
blocks not having correct relative route
#54864
Comments
This seems like either a framework or router issue. Material doesn't use the router at all. Transferring to the framework repo. |
Likely related to the injector construction of |
I could narrow it down a bit: The |
From what I tested in above stackblitz, the issue was introduced in v17.2.3 in this PR #52881 Later edit: |
@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. |
@defer
blocks not having correct relative route
…` class Currently, the `RouterOutlet` class uses a custom injector implementation to provide route-specific tokens (such as `ActivatedRoute`). This commit switches Router logic to use real `EnvironmentInjector` instead. This commit partially addresses issue angular#54864 and there will be one more PR with extra changes to defer logic.
…` class Currently, the `RouterOutlet` class uses a custom injector implementation to provide route-specific tokens (such as `ActivatedRoute`). This commit switches Router logic to use real `EnvironmentInjector` instead. This commit partially addresses issue angular#54864 and there will be one more PR with extra changes to defer logic.
…` class Currently, the `RouterOutlet` class uses a custom injector implementation to provide route-specific tokens (such as `ActivatedRoute`). This commit switches Router logic to use real `EnvironmentInjector` instead. This commit partially addresses issue angular#54864 and there will be one more PR with extra changes to defer logic.
…ocks This commit updates the `@defer` logic to establish proper injector resolution order. More specifically: - Makes node injectors to be inspected first, similar to how it happens when `@defer` block is not used. - Adds extra handling for the Router's `OutletInjector`, until we replace it with an `EnvironmentInjector`. Resolves angular#54864. Resolves angular#55028. Resolves angular#55036.
…ocks (angular#55079) This commit updates the `@defer` logic to establish proper injector resolution order. More specifically: - Makes node injectors to be inspected first, similar to how it happens when `@defer` block is not used. - Adds extra handling for the Router's `OutletInjector`, until we replace it with an `EnvironmentInjector`. Resolves angular#54864. Resolves angular#55028. Resolves angular#55036. PR Close angular#55079
@AndrewKushnir I found this page debugging an issue today… and think I have a related issue with update: tested with angular v17.3.3 and v17.3.4 It's not with the active route being undefined, it's with it having a stale value. I had a user report a broken link on a page in our app. We have a page that contains a list of posts. Everything works fine when viewing a feed for the first time. The links are correct. However, if the user navigates away to another page in the app, and then navigates to a different feed… (same component structure, but a different URL, think /feed/A vs /feed/B -- the route config is /feed/:feedID) Not sure if that's enough info to debug. I don't really know how to put together a stackblitz. |
It's not, unfortunately. A reproduction is really needed for us to investigate.
Can you create a minimal GitHub repo instead? |
working on it. it's at that infuriating stage. There is definitely a bug somewhere. I can't prove it's in angular yet, but I can't prove it's not. The fact that removing defer corrects the routerLink URLs sure smells like angular. I've disabled all guards and resolvers and ruled out those. 3+ hours, not how I want to spend my free time 😅 but the gap must be closing… |
@bboyle @atscott I updated my stackblitz to reproduce the issue. |
Until there is a fix we have rolled back to 17.2 (again). |
We had the same issue as well. Fortunately in our case we were able to refactor some components to avoid the stale values inside the |
Should we be making a new bug report for this? |
@AndrewKushnir is out of office until next week. I made the reproduction a bit smaller: https://stackblitz.com/edit/stackblitz-starters-uxf7bm |
FYI I don't have |
I have reproduced the issue -- here is a git repo you can run locally to see it in action: https://github.com/bboyle/angular-defer-routerlink Follow the instructions on screen and you will get to a state where some links (which use The issue occurs when factors required to reproduce this bug:
let me know if you need any more details |
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 The problem occur with a component from
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 The problem disappears if I remove I'm on Angular |
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. |
…er` blocks `RouterOutlet` uses a unique injector logic that returns a value that correspond to the `ActivatedRoute` token dynamically. This logic breaks when a component/directive/pipe that injects the `ActivatedRoute` is located within a `@defer` block, because defer creates an `EnvironmentInjector` instance, which doesn't have that dynamic logic. We've added some special handling of the `OutletInjector` in one of the previous commits, but it was incomplete and it was not covering cases when different routes use the same component. This commit updates defer logic to re-establish this dynamic behavior for `ActivatedRoute` by creating an instance of the `OutletInjector` when a parent injector was also an instance of `OutletInjector`. This fix is a short-term solution and longer term we should find a way to achieve the dynamic behavior that Router relies on, but without adding a special case logic into defer. Resolves angular#54864.
…er` blocks `RouterOutlet` uses a unique injector logic that returns a value that correspond to the `ActivatedRoute` token dynamically. This logic breaks when a component/directive/pipe that injects the `ActivatedRoute` is located within a `@defer` block, because defer creates an `EnvironmentInjector` instance, which doesn't have that dynamic logic. We've added some special handling of the `OutletInjector` in one of the previous commits, but it was incomplete and it was not covering cases when different routes use the same component. This commit updates defer logic to re-establish this dynamic behavior for `ActivatedRoute` by creating an instance of the `OutletInjector` when a parent injector was also an instance of `OutletInjector`. This fix is a short-term solution and longer term we should find a way to achieve the dynamic behavior that Router relies on, but without adding a special case logic into defer. Resolves angular#54864.
…er` blocks `RouterOutlet` uses a unique injector logic that returns a value that correspond to the `ActivatedRoute` token dynamically. This logic breaks when a component/directive/pipe that injects the `ActivatedRoute` is located within a `@defer` block, because defer creates an `EnvironmentInjector` instance, which doesn't have that dynamic logic. We've added some special handling of the `OutletInjector` in one of the previous commits, but it was incomplete and it was not covering cases when different routes use the same component. This commit updates defer logic to re-establish this dynamic behavior for `ActivatedRoute` by creating an instance of the `OutletInjector` when a parent injector was also an instance of `OutletInjector`. This fix is a short-term solution and longer term we should find a way to achieve the dynamic behavior that Router relies on, but without adding a special case logic into defer. Resolves angular#54864.
…er` blocks `RouterOutlet` uses a unique injector logic that returns a value that correspond to the `ActivatedRoute` token dynamically. This logic breaks when a component/directive/pipe that injects the `ActivatedRoute` is located within a `@defer` block, because defer creates an `EnvironmentInjector` instance, which doesn't have that dynamic logic. We've added some special handling of the `OutletInjector` in one of the previous commits, but it was incomplete and it was not covering cases when different routes use the same component. This commit updates defer logic to re-establish this dynamic behavior for `ActivatedRoute` by creating an instance of the `OutletInjector` when a parent injector was also an instance of `OutletInjector`. This fix is a short-term solution and longer term we should find a way to achieve the dynamic behavior that Router relies on, but without adding a special case logic into defer. Resolves angular#54864.
…er` blocks (#55374) `RouterOutlet` uses a unique injector logic that returns a value that correspond to the `ActivatedRoute` token dynamically. This logic breaks when a component/directive/pipe that injects the `ActivatedRoute` is located within a `@defer` block, because defer creates an `EnvironmentInjector` instance, which doesn't have that dynamic logic. We've added some special handling of the `OutletInjector` in one of the previous commits, but it was incomplete and it was not covering cases when different routes use the same component. This commit updates defer logic to re-establish this dynamic behavior for `ActivatedRoute` by creating an instance of the `OutletInjector` when a parent injector was also an instance of `OutletInjector`. This fix is a short-term solution and longer term we should find a way to achieve the dynamic behavior that Router relies on, but without adding a special case logic into defer. Resolves #54864. PR Close #55374
FYI, the fix from PR #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. |
Hello @AndrewKushnir, thanks a lot for the fix. I can confirm on my side that it is working now! |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Is this a regression?
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.Reproduction
StackBlitz link: https://stackblitz.com/edit/stackblitz-starters-prh2zk
Steps to reproduce:
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
The text was updated successfully, but these errors were encountered: