Skip to content
Advertisement

How to implement @HostListener(‘window:beforeunload’, [‘$event’]) into canDeactivate guard directives?

In my app, we have lots of components with lots of form fields. So whenever the user changes something in the form and without saving the changes if the user wants to navigate to another component he is getting a warning message using canDeactivate. However, instead of navigating to the app, if the user closes the tab then he is not getting the warning message anymore. I have resolved this issue using window:beforeunload inside the component like this:

@HostListener('window:beforeunload', ['$event'])
  public oncloseTab( event: KeyboardEvent) {
    if (this.shouldWarnForUnsaved()) {  // shouldWarnForUnsaved tells if anything changes in the form 
      return window.confirm('There is the unsaved message. Are you sure you want to close the tab?');
    }
  }

However as I said I have lots of components, so I have to do the copy-paste this above code several times in several components. I am just curious, is there any way I could achieve using candeactivate guard directive? My goal is, I will implement the beforeunload once in the candeactivate guard directives so that I do not have to repeat the same code in several times.

Can anybody have any clue how to do this?

Advertisement

Answer

You can just create a custom directive and add this to every form which has a formGroup directive attached to it if you use reactive forms, or ngForm when you use template driven:

@Directive({
  selector: '[formUnloadWarning]'
})
export class FormUnloadWarningDirective {
  private form = this.reactiveForm || this.templateForm;

  constructor(
    @Self() @Optional() private reactiveForm: FormGroup,
    @Self() @Optional() private templateForm: NgForm
  ) {}

  @HostListener('window:beforeunload', ['$event'])
  onBeforeUnload() {
    if (this.form.dirty) {
      return window.confirm('There is the unsaved message....');
    }
  }
}

Which you can then use on your forms like this:

Reactive forms:

<form formUnloadWarning [formGroup]="form" (ngSubmit)="onSubmit()">
  <!-- your controls -->
</form>

Template driven:

<form formUnloadWarning #reqForm="ngForm">
  <!-- your form -->
</form>
Advertisement