Browser Back Button default behavior still executing on stop propigation

Viewed 867

I have an angular site in which I've inserted some code to make the browser back button behave in the same way as the back UI button. However when I press back on the browser I get the last visited page flashing for a second before the default behavior executes.

Here's a video to show what I mean - at the end I show the what clicking the UI button does which is what I want to emulate: Browser Back Button Demo

And here's the code I'm using in Angular:

@HostListener('window:popstate', ['$event'])
  onBrowserBackBtnClose(event: Event) {
      // Stop default behavior of the back button
      event.stopPropagation();
      event.preventDefault();
      // If we can go back...
      if (this.canGoBack) {
        // Load the previous question
        this.questionService.previousQuestion().subscribe(res => {
          // Activate the question route in place of the previous page
          this.router.navigate(['question'], {replaceUrl: true});
        });
      }
  }

My understanding was that event.stopPropagation(); and event.preventDefault(); stopped this flickering behavior? Or is there something else I'm not understanding or missing?

2 Answers

If I was you I would rather use native Angular approach here. In this particular case you can implement CanDeactivate or CanActivate Route Guards.

In both of this interfaces methods uses asynchronous returns such as:

Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree

You cannot cancel popstate event in the browser, read more about the event on MDN page. That being said, you can update window history (technically a hack) and push current location again so that page will be navigated back to current page using:

window.history.pushState(null, null, window.location.pathname);

Not sure, how you can apply it to your code as I do not have working demo of your app, but it could look something like:

@HostListener('window:popstate', ['$event'])
onBrowserBackBtnClose(event: Event) {
  // prevent browser from moving to different page
  window.history.pushState(null, null, window.location.pathname);
      
  // If we can go back...
  if (this.canGoBack) {
    // Load the previous question
    this.questionService.previousQuestion().subscribe(res => {
      // Activate the question route in place of the previous page
      this.router.navigate(['question'], {
        replaceUrl: true
      }); // you will need some other code to determine and navigate to next page if user chooses to
    });
  }
}

Related