0

I want to handle browser's back button action with confirm message. If I click Yes, browser has to redirect to previous state and If I click No, need to stay in same state. This need to be handle in Angular. Please correct my code and thanks.

@HostListener('window:popstate', ['$event'])
  onPopState(event: any) {
    var stayOnPage = event.currentTarget.confirm("Are you sure want to go back?");
    if (!stayOnPage) {        
       event.preventDefault(); >> not working
       return false;
    } else {
       
    }
  }
YYY
  • 3,440
  • 5
  • 20
  • 24

1 Answers1

1

You need to do the following in the Angular way:

  • Have a guard service that implements CanDeactivate (called when you navigate away from a page), and configure your router to use it
  • Listen to router events in the page where you want the option to prevent the Back button from working

I also implemented a generic confirmation material dialog and service.

See the full example on Stackblitz here. Below is the important code snippets:

App Routes

const routes: Routes = [
  /**
   * About page is where we are guarding the navigation
   */
  { path: "about", component: AboutComponent, canDeactivate: [NavigationGuardService] },
  { path: "", component: HomeComponent }
];

Navigation Guard

import { Injectable } from "@angular/core";
import { CanDeactivate } from "@angular/router";
import { Observable } from "rxjs";
import { DataService } from "./data.service";

export interface DeactivationGuarded {
  canDeactivate(): Observable<boolean> | Promise<boolean> | boolean;
}

@Injectable()
export class NavigationGuardService implements CanDeactivate<any> {
  constructor(private dataService: DataService) {}

  /**
   * Angular calls it when navigating away from the backFromAboutPage
   * Notice it is asynvhronous in our case because we are waiting for the user
   * to confirm or deny
   */
  canDeactivate(component: DeactivationGuarded): boolean | Observable<boolean> | Promise<boolean> {
    if (!this.dataService.backFromAboutPage) {
      return true;
    }

    return component.canDeactivate ? component.canDeactivate() : true;
  }
}

The Monitored Page

import { Component, OnDestroy, OnInit } from "@angular/core";
import { MatDialogConfig } from "@angular/material/dialog";
import { NavigationStart, Router } from "@angular/router";
import { Observable, Subscription } from "rxjs";
import { filter } from "rxjs/operators";
import { ConfirmationDialogService } from "../confirmation-dialog.service";
import { DataService } from "../data.service";
import { DeactivationGuarded } from "../navigation-guard.service";

@Component({
  selector: "app-about",
  templateUrl: "./about.component.html",
  styleUrls: ["./about.component.css"]
})
export class AboutComponent implements OnInit, OnDestroy, DeactivationGuarded {
  routerSubscription: Subscription;

  constructor(
    private dataService: DataService,
    private router: Router,
    private confirmationDialogService: ConfirmationDialogService
  ) {}

  ngOnInit(): void {
    /**
     * Listen to the router events to identify when the user navigates away from the page
     * and distinguish between Back button and other means of navigation
     */
    this.routerSubscription = this.router.events
      .pipe(filter(event => event instanceof NavigationStart))
      .subscribe((event: NavigationStart) => {
        if (event.navigationTrigger == "popstate" && event.restoredState) {
          this.dataService.backFromAboutPage = true;
        } else {
          this.dataService.backFromAboutPage = false;
        }
        console.log("Back button:", this.dataService.backFromAboutPage);
      });
  }

  ngOnDestroy(): void {
    this.routerSubscription.unsubscribe();
  }

  /**
   * Called from the navigation guard when navigating away from the page
   * Here we show the confirmation dialog
   */
  canDeactivate(): boolean | Observable<boolean> | Promise<boolean> {
    const dialogConfig: MatDialogConfig = {
      data: {
        title: "",
        content: `Go Back?`
      }
    };

    this.confirmationDialogService.openDialog(dialogConfig);

    return this.confirmationDialogService.back$.asObservable();
  }
}
Benny Halperin
  • 1,872
  • 3
  • 13
  • 18