3

I have a guard set in place in order to show a warning when the user switches and/or refreshes the page. I also implemented a way to call the function ngOnDestroy when these actions are made.

Problem: When the user refreshes trys to leave the website, the popup is show correctly, but no matter what he chooses, ngOnDestroy is called. So, the function is trigger even if he doesn't refresh the page. I want to implement a way that the function is only called when he accepts the default alert and the page does indeed refresh.

show-quiz.module.ts
ngOnInit(): void {
  window.onbeforeunload = () => this.ngOnDestroy();   //Call ngOnDestroy when the user closes/switches the tab
}

//Stop timer when the component is destroyed
ngOnDestroy(): void {
  // If the user is in the middle of the exam, save the data
  if (!this.end) {
    this.checkAnswers();
  }
}

//@HostListener allows us to also guard against browser refresh, close, etc.
@HostListener('window:beforeunload')
canDeactivate(): Observable<boolean> | boolean {
  // insert logic to check if there are pending changes here;
  // returning true will navigate without confirmation
  // returning false will show a confirm dialog before navigating away
  return this.end;
}
app-routing.module.ts
{ path: 'show-quiz', component: ShowQuizComponent, canDeactivate: [PendingChangesGuard] }
pending-changes.guard.ts
export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
  canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> {
    // if there are no pending changes, just allow deactivation; else confirm first
    return component.canDeactivate() ?
      true :
      // NOTE: this warning message will only be shown when navigating elsewhere within your angular app;
      // when navigating away from your angular app, the browser will show a generic warning message
      // see http://stackoverflow.com/a/42207299/7307355
      confirm('ATENÇÃO: Alterações podem não ter sido guardadas. Tem a certeza que deseja sair?');
  }
}
André Clérigo
  • 846
  • 1
  • 10
  • 30
  • When exactly your ngDestroy get call? When using angular route? Or when you close the browser tab? If it's the latter then it's normal, this is browser thing, angular cannot intercept it. (your code comment say it all - trigger when close tab + only trigger when navigating using angular route) – Jimmy Sep 13 '22 at 05:56
  • canDeactivate is also called when the user refreshes the page @Jimmy – André Clérigo Sep 13 '22 at 10:12
  • No it won't. These are 2 different things: your app and the browser. You can only control your app, which mean, navigating around by routerLink will work. But closing tab, refresh, killing brower's process or shut down the computer, your app just can't control it. – Jimmy Sep 13 '22 at 16:10
  • I already implemented that a function is called ngOnDestroy when the user switches component and accepts the warning message, I just want to do the same when the user closes/refreshes the browser. Right now, the default refresh message popups and regardless the user's answer ngOnDestroy is called – André Clérigo Sep 13 '22 at 18:52
  • You can check this link: https://css-tricks.com/send-an-http-request-on-page-exit/. You will find out why unload/beforeunload is not a choice in those cases – Jimmy Sep 13 '22 at 19:14
  • Whatever, if window.onbeforeunload doesn't work there must be a way! This is a trivial feature in a robust app – André Clérigo Sep 13 '22 at 19:18

0 Answers0