JayJang
JayJang

Reputation: 3

Angular How to detect browser back button press before route changing

I'm using Angular 12 SPA app. When user press the browser back button. I want to show the warning message before leave in current route url. Current page "localhost/note"

If user click back button. url changed "localhost/home" then show the warning message(page is not changed, only url changed)

However, I want to show the message BEFORE route change. I'm using HostListener. It shows alert after url/route change

@HostListener('window:popstate', ['$event'])
  onPopState(event: any) {
    alert("Do you really want to move other page?");
  }

Upvotes: 0

Views: 5202

Answers (1)

mat.hudak
mat.hudak

Reputation: 3228

welcome to the stackoverflow. What you are looking for is onbeforeunload event, it should do the job. But check it here, some browsers have limitations for it (like blocking pop-ups).

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

  @HostListener('window:beforeunload', ['$event'])
  unloadNotification($event: any) {
    if (!AuthService.isLogout && !this.canDeactivate()) {
      $event.returnValue = true;
    }
  }
}

We used the code above together with a route guard which check Angular Router navigation. If result of canDeactivate is false, route guard won't let you leave the current route.

@Injectable({
  providedIn: 'root',
})
export class UnsavedChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
  constructor() {}

  canDeactivate(
    component: FormCanDeactivate,
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot,
    next: RouterStateSnapshot
  ): boolean | Observable<boolean> {
    const someUrlCheck = next.url.includes(someRoute);
    return component.canDeactivate() ? true : component.openConfirmCancelDialog(someUrlCheck);
  }
}

In our case FormCanDeactivate abstract class extends another ComponentCanDeactivateabstract class and provides default 'Are you sure you want to leave' dialog.

@Directive()
export abstract class FormCanDeactivate extends ComponentCanDeactivate {
  private _dialogConfig: ConfirmDialogData = initialDialogConfig;
  protected disableDiscard: boolean = false;

  get dialogConfig(): ConfirmDialogData {
    return this._dialogConfig;
  }

  set dialogConfig(value: ConfirmDialogData) {
    this._dialogConfig = value;
  }

  abstract get saveForm(): FormGroup | boolean;

  abstract submitForm(): void;

  abstract resetForm(): void;

  constructor(protected dialog: MatDialog) {
    super();
  }

  openConfirmCancelDialog(isLogout: boolean = false): Observable<boolean> {
    // ...
  }

  canDeactivate(): boolean {
    // ...
  }
}

Upvotes: 1

Related Questions