1
votes

In my Angular 7 app, I have a canDeactivate guard to alert user of unsaved changes. This guard also guard from leaving the page

  @HostListener('window:beforeunload')
  public canDeactivate(): boolean {
    return this.contentChanged === false;
  }

On the same page, I have some function to download from AWS S3

  async downloadAttachment(url: string, e: any) {
    const target = e.target || e.srcElement || e.currentTarget;
    window.onbeforeunload = null;
    if (!target.href) {
      e.preventDefault();
      target.href = await this.storageService.getDownloadLink(
        url,
      );
      target.download = this.storageService.getFileName(url);
      target.click();
    }
  }

The issue is when I have unsaved changes(contentChanged=true), the download will trigger the window:beforeunload event and the browser will alert enter image description here

and user has to click "Leave" to download the file. The downloading process does not leave the page actually.

I tried to add "window.onbeforeunload = null" in the code, but it does not work in my code.

How to allow user to download without seeing the meaningless alert?

1

1 Answers

1
votes

You could define a flag isDownloadingFile in the guard, and set it before starting the download:

constructor(private canDeactivateGuard: CanDeactivateGuard) { }

async downloadAttachment(url: string, e: any) {
  const target = e.target || e.srcElement || e.currentTarget;
  if (!target.href) {
    e.preventDefault();
    this.canDeactivateGuard.isDownloadingFile = true; // <---------------- Set flag
    target.href = await this.storageService.getDownloadLink(url);
    target.download = this.storageService.getFileName(url);
    target.click();
  }
}

You would then check and reset that flag in canDeactivate:

@Injectable()
export class CanDeactivateGuard {

  public isDownloadingFile = false;

  @HostListener('window:beforeunload')
  public canDeactivate(): boolean {
    const result = this.isDownloadingFile || !this.contentChanged; // <--- Check flag
    this.isDownloadingFile = false; // <---------------------------------- Reset flag
    return result;
  }

  ...
}