52

I have a component and I need to detect if user pressed back button in his browser to navigate back.

Currently I'm subscribing router events.

constructor(private router: Router, private activatedRoute: ActivatedRoute) {

    this.routerSubscription = router.events
        .subscribe(event => {

            // if (event.navigatesBack()) ...

        });

}

I know that I can use window.onpopstate but it feels like a hack when using Angular2.

Michał Pietraszko
  • 5,666
  • 3
  • 21
  • 27

6 Answers6

46

EDIT Please don't do this.

The official docs say "This class should not be used directly by an application developer. Instead, use Location." Ref: https://angular.io/api/common/PlatformLocation


It's possible to use PlatformLocation which has onPopState listener.

import { PlatformLocation } from '@angular/common'

(...)

constructor(location: PlatformLocation) {

    location.onPopState(() => {

        console.log('pressed back!');

    });

}

(...)
rmcsharry
  • 5,363
  • 6
  • 65
  • 108
Michał Pietraszko
  • 5,666
  • 3
  • 21
  • 27
44

IMO better method of listenting for popstate events is to subscribe to location service

import {Location} from "@angular/common";

constructor(private location: Location) { }

ngOnInit() {
    this.location.subscribe(x => console.log(x));
}

It doesn't use PlatformLocation directly (as documentation suggest) and you can unsubscribe any time you want.

thorin87
  • 2,210
  • 1
  • 17
  • 6
  • 8
    Don't forget to unsubscribe in ngOnDestroy() ! – Humppakäräjät Sep 13 '17 at 09:30
  • 2
    As an alternative you could subscribe to route.params.subscribe(...); Difference is that it will already fire when you initial enter the page, which location.subscribe(...) doesn't. The latter only fires when the parameter actually has changed. – Humppakäräjät Sep 13 '17 at 09:37
  • 1
    @Humppakäräjät how does that help to tell if user navigated back or not? There is no access to the history api in route.. – Mackelito Nov 28 '17 at 08:41
  • @Mackelito yes you are right it won't directly detect if he went back or forth. It only fires when it has detected that the route parameters have changed, which might happen when the user hits the browsers back or forth button. – Humppakäräjät Nov 28 '17 at 13:30
  • But wont that happen on any navigation? – Mackelito Nov 28 '17 at 14:08
  • I'm not sure if it would detect if the previous page had the exact same url. But what would you change then, anyways ;) – Humppakäräjät Nov 28 '17 at 14:39
  • 2
    @Humppakäräjät *It only fires when it has detected that the route parameters have changed, which might happen when the user hits the browsers back or forth button.* - so as it only **might work** it is useless. – Antoniossss Jul 27 '18 at 08:42
  • It doesnot provide a solution for user navigating back – Gvs Akhil Jan 29 '20 at 08:44
24
import { HostListener } from '@angular/core';

and then listen for popstate on the window object:

  @HostListener('window:popstate', ['$event'])
  onPopState(event) {
    console.log('Back button pressed');
  }

This code works for me on latest Angular 2.

VSO
  • 11,546
  • 25
  • 99
  • 187
4

As thorin87 answer dont use PlatformLocation. We need subscribe an unsubscribe.

import {Subscription} from 'rxjs/Subscription';    

ngOnInit() {
  this.subscription = <Subscription>this
    .location
    .subscribe(() => x => console.log(x));
}

ngOnDestroy() {
  this.subscription.unsubscribe();
}
Sonu Kapoor
  • 1,567
  • 3
  • 16
  • 34
omi5489
  • 381
  • 3
  • 8
4

in angular 8+

constructor(private readonly route: Router) {
this.route.events
  .pipe(filter((event) => event instanceof NavigationStart))
  .subscribe((event: NavigationStart) => {
    if (event.restoredState) {
      this.isBackUrl = true;
    }
  });

}

Milad Jafari
  • 970
  • 10
  • 15
-2

This solution works for all versions of Angular.

import { PlatformLocation } from'@angular/common';

constructor( private _location: PlatformLocation ) {

this._location.onPopState (() => {
 `enter code here` // You could write code to display a custom pop-up here.

 // window.location.href = 'https://www.google.com'; //Navigate to another location when the browser back is clicked.


});
Peyman Mohamadpour
  • 17,954
  • 24
  • 89
  • 100
  • 1
    Official docs say "This class should not be used directly by an application developer. Instead, use Location." Ref: https://angular.io/api/common/PlatformLocation – rmcsharry May 24 '20 at 09:08