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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

HostListener is still listening after ngOnDestroy started #38100

Open
MarsiBarsi opened this issue Jul 16, 2020 · 2 comments
Open

HostListener is still listening after ngOnDestroy started #38100

MarsiBarsi opened this issue Jul 16, 2020 · 2 comments
Labels
area: core Issues related to the framework runtime core: lifecycle hooks P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent type: confusing
Milestone

Comments

@MarsiBarsi
Copy link
Contributor

馃悶 bug report

Affected Package

@angular/core

Is this a regression?

No, I caught this bug in a version 7 first

Description

There can be some situations in that we need to dispatch an event on component destroy.
If we have HostListener listening type of event we dispatch, it catches this.

So, in other words, HostListener continues listening even after ngOnDestroy has already started.

Is it a bug or by design?

馃敩 Minimal Reproduction

https://stackblitz.com/edit/angular-hostlintener-bug?file=src%2Fapp%2Fhello.component.ts

馃敟 Exception or Error

馃實 Your Environment

Angular Version:

10.0.1 and 
7.22.0

@ngbot ngbot bot added this to the needsTriage milestone Jul 16, 2020
@crisbeto
Copy link
Member

This might need some discussion, because I can see it going the other way. E.g. if you want to fire off one last listener before the component is destroyed. Also the behavior is consistent between ViewEngine and Ivy.

For future reference, here's a unit test that shows the behavior:

it('', () => {
  let counter = 0;

  @Directive({selector: '[hasHostListener]'})
  class DirectiveWithHostListener implements OnDestroy {
    constructor(private _elementRef: ElementRef<HTMLElement>) {}

    @HostListener('click')
    clicked() {
      counter++;
    }

    ngOnDestroy() {
      this._elementRef.nativeElement.click();
    }
  }

  @Component({template: `<button *ngIf="showButton" hasHostListener>Click me!</button>`})
  class App {
    showButton = true;
  }

  TestBed.configureTestingModule({declarations: [App, DirectiveWithHostListener]});
  const fixture = TestBed.createComponent(App);
  fixture.detectChanges();

  fixture.componentInstance.showButton = false;
  fixture.detectChanges();
  expect(counter).toBe(0);
});

@waterplea
Copy link
Contributor

waterplea commented Jul 20, 2020

It might be unclear which behavior is better but to the argument of the last listener there's a counter argument that a lot of the time events are handled with RxJS and common pattern is takeUntil(this.destroyedStream). This pattern completes manually in ngOnDestroy so past ngOnDestroy no events would be handled. Seems reasonable to me that we have hook that guarantees to be the end of the lifecycle, while currently it seems not to be the case.

@ngbot ngbot bot modified the milestones: needsTriage, Backlog Jul 27, 2020
@ngbot ngbot bot modified the milestones: Backlog, needsTriage Nov 28, 2021
@alxhub alxhub added the P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent label Nov 16, 2022
@ngbot ngbot bot modified the milestones: needsTriage, Backlog Nov 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: core Issues related to the framework runtime core: lifecycle hooks P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent type: confusing
Projects
None yet
Development

No branches or pull requests

6 participants