Skip to content
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

incorrect component passed to canDeactivate guard #34614

Open
FDIM opened this issue Jan 2, 2020 · 6 comments
Open

incorrect component passed to canDeactivate guard #34614

FDIM opened this issue Jan 2, 2020 · 6 comments

Comments

@FDIM
Copy link
Contributor

@FDIM FDIM commented Jan 2, 2020

🐞 bug report

Affected Package

The issue is caused by package @angular/router

Description

For some reason CanDeactivate guard gets called with an incorrect component instance.
In this case it should get called with a component that is mounted in a named outlet, but gets called with one from primary outlet. See example in stackblitz.

I'd expect that with configuration like below:
image
The guard should only be called when AdminHeaderComponent is being deactivated and only with this component instance.

One notable thing is that the currentRoute param is correct!
image

EDIT: found a workaround:

canDeactivate(component: HasComponentPendingChanges, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot) {
    if (currentRoute.outlet === OVERLAY_OUTLET && this.router['rootContexts'] && this.router['rootContexts'].getContext) {
        const context: OutletContext = this.router['rootContexts'].getContext(OVERLAY_OUTLET);
        if (context && context.outlet && context.outlet.isActivated && context.outlet['activated'].instance) {
            component = context.outlet['activated'].instance;
        }
    }

🔬 Minimal Reproduction

https://stackblitz.com/edit/angular-named-outlet-yfgsip?file=app%2Fadmin%2Fadmin.module.ts

  • Open the link
  • Open the console
  • Click on admin link
  • Click on create user link
  • Observe that following message is printed:
deactivating UsersListComponent {}
  • Now click on hide navbar link
    image

  • Observe that following messages are printed:

deactivating CreateUserComponent {}
deactivating AdminHeaderComponent {}

^ all good

  • Now the fun begins, click on admin and create user links again
  • Click on Component 2
  • Observe that following messages are printed:
deactivating UsersListComponent {}
deactivating CreateUserComponent {}
deactivating CreateUserComponent {}

I'd argue that the last message should state AdminHeaderComponent

🌍 Your Environment

Angular Version:


8.2.14
@ngbot ngbot bot added this to the needsTriage milestone Jan 3, 2020
@ngbot ngbot bot removed this from the needsTriage milestone Jan 15, 2020
@ngbot ngbot bot added this to the Backlog milestone Jan 15, 2020
@ngbot ngbot bot removed this from the needsTriage milestone Jan 15, 2020
@ngbot ngbot bot added this to the Backlog milestone Jan 15, 2020
@ngbot ngbot bot removed this from the needsTriage milestone Jan 15, 2020
@ngbot ngbot bot added this to the Backlog milestone Jan 15, 2020
@martinsik
Copy link
Contributor

@martinsik martinsik commented Mar 28, 2020

Just fyi this issue is present in Angular 9.1.0 as well: https://stackblitz.com/edit/angular-named-outlet-enygni?file=app%2Fapp.component.html

atscott added a commit to martinsik/angular that referenced this issue Apr 9, 2020
…g two or more sibling router-outlets

fixes angular#34614

There's an edge case where if I use two (or more) sibling <router-outlet>s in two (or more) child routes where their parent route doesn't have a component then preactivation will trigger all canDeactivate checks with the same component because it will use wrong OutletContext.
atscott added a commit that referenced this issue Apr 9, 2020
…g two or more sibling router-outlets (#36302)

fixes #34614

There's an edge case where if I use two (or more) sibling <router-outlet>s in two (or more) child routes where their parent route doesn't have a component then preactivation will trigger all canDeactivate checks with the same component because it will use wrong OutletContext.

PR Close #36302
@atscott atscott reopened this Apr 22, 2020
@atscott
Copy link
Contributor

@atscott atscott commented Apr 22, 2020

Reopening - fix was reverted because it did not work with some configs.

@FDIM
Copy link
Contributor Author

@FDIM FDIM commented Apr 22, 2020

I guess this process with reverting commits can be improved a bit by reopening related issues to avoid some confusion

@krilllind
Copy link

@krilllind krilllind commented Nov 19, 2020

I'm also experiencing the same issues, but my component param in canDeactivate returns null instead of wrong component. This happens when my named outlet is present in parent route component template.

I found this bug in version 10.0.2 but was able to reproduce in latest 11.0.1
https://stackblitz.com/edit/angular-ivy-efvmyh?file=src/app/can-deactivate-page.guard.ts

I believe my issue is related to the same as this

Expected

Console should display following messages:
"canDeactivate was called" (instance of LazyComponent)
"onPageDeactivation was called"

Actual behaviour

Console only outputs:
"canDeactivate was called" (null)

@reinvanleirsberghe
Copy link

@reinvanleirsberghe reinvanleirsberghe commented Jan 8, 2021

Having the same issue als @krilllind
image
With outlet my component is null

@martinsik
Copy link
Contributor

@martinsik martinsik commented Feb 23, 2022

Seems to be still broken in Angular 13.
This is updated stackblitz for Angular 13: https://stackblitz.com/edit/angular-ivy-71zp9t?file=src%2Fapp%2Fapp.module.ts

I tried to fix it in #36302, but this PR was closed because it was supposed to be fix in another PR. However, that fix was reverted and I don't remember how I fixed it in #36302 because that's been two years already...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants