1
votes

In my Angular 11 app, I am trying to implement a way to warn the user that there is unsaved data on the page.

For simplicity, let's consider that we only care when a user closes or refreshes the tab.

Basically, I was following the following implementation that was made in Angular 5: https://stackblitz.com/edit/angular-rgsa51?file=app%2Fform-can-deactivate%2Fform-can-deactivate.ts

I have a generic component that will handle the window:beforeunload event:

@Directive()
export abstract class CanDeactivateComponent {
  public abstract canDeactivate(): boolean;

  @HostListener('window:beforeunload', ['$event'])
  public unloadNotification($event: any): void {
    console.log( '[CanDeactivateComponent] window:beforeunload ' );

    if (!this.canDeactivate()) {
      // triggers a browser confirmation dialog asking the user if they really want to leave the page
      // most modern browsers will just present a generic message.
      $event.returnValue = true;
    }
  }
}

And then, a component that is customized for Angular Forms:

export abstract class CanDeactivateFormComponent extends CanDeactivateComponent {
  public abstract formGroup: FormGroup;
  public abstract initialValue: {};

  public canDeactivate(): boolean {
    return JSON.stringify(this.initialValue) === JSON.stringify(this.formGroup.value);
  }
}

My form component is implemented:

@Component({
  ...
})
export class MyFormComponent extends CanDeactivateFormComponent { ... }

The problem now is that thewindow:beforeunload seeems to get triggered twice (please check the console.log message)

The full code is here: https://stackblitz.com/edit/angular-ivy-xu5vq8?file=src%2Fapp%2Fcan-deactivate.component.ts

1

1 Answers

1
votes

Its weird, but interesting how angular works,

let say we have 3 class hierarchy

A->B->C

A has host listener so u have to decorate it with Directive

B is not don't need anything

C is a component.

why host listener is being called twice ? I don't know but what will happen when I add other class in hierarchy lets call it BB and BB is has no decorator as well.

so now hierarchy is

A->B->BB->C

now host listener is being called 2 + 1 = 3 time u can verify.

good now we know bcs of class hierarchy its calling host listener more then one time.

how to resolve it ?

decorate each class in hierarchy by doing it host listener will be called just once.

and other weird thing if u just decorate immediate child of A, (B) with decorator and don't decorate BB it will call host listener just once.

But better to decorate each class in hierarchy, so maybe in future someone add host listener to parent class, it does cause issue.