How to Detect Browser Back Button Click Event Using Angular

Angular 2 How to detect back button press using router and location.go()?

I don't know if the other answers are dated, but neither of them worked well for me in Angular 7. What I did was add an Angular event listener by importing it into my component:

import { HostListener } from '@angular/core';

and then listening for popstate on the window object (as Adrian recommended):

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

This worked for me.

Angular How to detect browser back button press before route changing

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 {
// ...
}
}

How to detect browser back button click event using angular?

Here is a solution with Angular.

myApp.run(function($rootScope, $route, $location){
//Bind the `$locationChangeSuccess` event on the rootScope, so that we dont need to
//bind in induvidual controllers.

$rootScope.$on('$locationChangeSuccess', function() {
$rootScope.actualLocation = $location.path();
});

$rootScope.$watch(function () {return $location.path()}, function (newLocation, oldLocation) {
if($rootScope.actualLocation === newLocation) {
alert('Why did you use history back?');
}
});
});

I am using a run block to kickstart this. First I store the actual location in $rootScope.actualLocation, then I listen to $locationChangeSuccess and when it happens I update actualLocation with the new value.

In the $rootScope I watch for changes in the location path and if the new location is equal to previousLocation is because the $locationChangeSuccess was not fired, meaning the user has used the history back.

How do I detect user navigating back in Angular2?


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!');

});

}

(...)

How can catch when user clicked back button in browser and show modal in Angular

According to the angular.io, you can create a CanDeactivate guard for this kind of uses.

I started from a simple example having two routes with two components HelloComponent and ByeComponent. To leave the HelloComponent, a confirmation dialog is displayed.

First I copied the CanDeactivateGuard from the angular.io example :

import { Injectable }    from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { Observable } from 'rxjs';

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

@Injectable({
providedIn: 'root'
})
export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
canDeactivate(component: CanComponentDeactivate) {
return component.canDeactivate ? component.canDeactivate() : true;
}
}

Then I added the CanDeactivate to the routing of component that need confirmation :

@NgModule({
imports: [
RouterModule.forChild([
{ path: '', component: HelloComponent, canDeactivate: [CanDeactivateGuard] }
])
],
exports: [RouterModule]
})
export class HelloRoutingModule { }

Finally implemented the canDeactivate function in the related component :

canDeactivate() {
return confirm('Are you sure you want to leave Hello ?');
}

Here is the link for the running example.



Related Topics



Leave a reply



Submit