-
Notifications
You must be signed in to change notification settings - Fork 26.3k
fix(router): deactivate outlet if already activated when calling acti… #20712
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
fix(router): deactivate outlet if already activated when calling acti… #20712
Conversation
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please visit https://cla.developers.google.com/ to sign. Once you've signed, please reply here (e.g.
|
I signed it! |
We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for the commit author(s). If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google. |
7f6a346
to
d265180
Compare
CLAs look good, thanks! |
Hi there, it seems Travis failed because of the issues they're having with Chrome at the moment. If there is a chance to restart the build it might pass (I can't). Thank you |
Why did you change the engine tag in the package.json. I don't really see how that's related to a PR about routing? |
@Riobe that was my mistake. Reverted the changes. |
e7d6e60
to
d265180
Compare
…vateWith Instead of throwing an error, we are now able to deactivate the outlet before activating it again with a new route. This makes routing configuration more flexible when we have named outlets we want to re-use on different routes with nested child routes Closes angular#20694
d265180
to
ab870e0
Compare
Will this get merged in? |
@gigadie When is this going to get merged in? We are facing the same issues. |
We have also same problem and fix above helps, what are the plans for merging it in? |
when will the fix be done? |
When will this be merged guys? |
I found solution (not the best but completely working) @ViewChild(RouterOutlet) outlet: RouterOutlet;
constructor(
private router: Router
) { }
ngOnInit(): void {
this.router.events.subscribe(e => {
if (e instanceof ActivationStart && e.snapshot.outlet === "admin-panel")
this.outlet.deactivate();
});
} |
This change doesn't fix the underlying problem: router outlets sometimes remain "activated" after navigating away from them. Throwing an error is still the correct behavior when an outlet is indeed active and something tries to activate it again. There has to be another way to fix this problem. |
My effect of problemIn my case we dynamically create modal dialogs with a named router outlet in there.
If I just delete my outlet from the map it works for my case:
I understand the OutletContext needs to be still referenced for the use case of the NgIf for restoring. For me as user this is first irritating: Especially because I explicitly call deactivate on my referenced RouterOutlet and it then says it is still activated? export class FooComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild(RouterOutlet)
public routerOutlet: RouterOutlet;
constructor(private router: Router) {
}
public ngOnInit() {
// This one works actually:
// this.router.events.subscribe(e => {
// if (e instanceof ActivationStart && e.snapshot.outlet === FinancesRoutingRouteNames.PaymentOutlet) {
// this.routerOutlet.deactivate();
// }
// });
}
public ngAfterViewInit() {
console.log(this.routerOutlet);
}
public ngOnDestroy() {
this.routerOutlet.deactivate();
}
} Then if you look, you see that the messages means the OutletContext and not the RouterOutlet.
Here it sets the RouterOutlet on the parentContexts ( private parentContexts: ChildrenOutletContexts ) which calls:
Which then creates or gets a already existing OutletContext:
More investigationMaybe this is the wrong direction but I see the 1# place:
First time my outlet is created it is not firing the activateWith in the ngOnInit method. Then this is called in the ActivateRoutes class (2# place:): // outlet: RouterOutlet | null
if (context.outlet) {
// Activate the outlet when it has already been instantiated
// Otherwise it will get activated from its `ngOnInit` when instantiated
context.outlet.activateWith(future, cmpFactoryResolver);
} Then I remembered this method:
Questions:Is this related: Possible solutionIf I just remove the activateWith call in the else block in the ngOnInit method of the RouterOutlet everything seems to work as expected in my application. https://github.com/angular/angular/blob/master/packages/router/src/directives/router_outlet.ts#L69 Another side effectMy Router Outlets from the URL aren't removed by refreshing in the browser. So I got problems also with this and wrote the following: // export const PRIMARY_OUTLET = 'primary';
private clearRouterOutlets() {
const urlTree = this.router.createUrlTree([]);
const clearingOutlets: {[outlet: string]: null} = {};
const primaryOutletName = PRIMARY_OUTLET;
// Get all router outlet names except the primary router outlet and remove them.
Object.keys(urlTree.root.children)
.filter(outletName => outletName !== primaryOutletName)
.forEach(remainingOutletName => clearingOutlets[remainingOutletName] = null);
this.router.navigate([
{
outlets: clearingOutlets
}
]);
} This is then also working and the (outlet) urls queries are removed on refresh of the page. But before the Error was thrown again. But with the above suggestion it is also working. |
I experience the same issue as @StefanRein described. |
Running into the exact same case as @StefanRein The description there is 👌 |
What happened, guys? |
Any news on this matter? |
Anything we can do to help this move forward? |
Closing, for two main reasons:
The issue happens before we get to the |
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. |
fix(router): deactivate outlet if already activated when calling activateWith
Instead of throwing an error, we are now able to deactivate the outlet before activating it again with a new route. This makes routing configuration more flexible when we have named outlets we want to re-use on different routes with nested child routes
Closes #20694
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
I described the current behavior in the issue #20694, the router throws an error when the user tries to navigate from one route
/home
to another/about
and the routing config is defined as follows:Issue Number: #20694
What is the new behavior?
With the new behavior, instead of throwing an error, it simply deactivates the current outlet route, before activating the new one.
Does this PR introduce a breaking change?