30

I'm developing a web site using Angular 2. Is there any way to disable or trigger Browser back button using Angular 2?

Thanks

DAN
  • 3,140
  • 5
  • 20
  • 22

15 Answers15

36

Not sure if this is already sorted, but posting the answer nonetheless, for future references. To tackle this, you basically need to add a listener in your app-component and setup a canDeactivate guard on your angular-router.

// in app.component.ts
import { LocationStrategy } from '@angular/common';

@Component({
  selector: 'app-root'
})
export class AppComponent {
  constructor(
    private location: LocationStrategy
  ) {
    // check if back or forward button is pressed.
    this.location.onPopState(() => {
      // set isBackButtonClicked to true.
      this.someNavigationService.setBackClicked(true);
      return false;
    });
  }
}

// in navigation guard
@Injectable()
export class NavigationGuard implements CanDeactivate<any> {
  constructor(private someNavigationService: SomeNavigationService) {}
  canDeactivate(component: any) {
    // will prevent user from going back
    if (this.someNavigationService.getBackClicked()) {
      this.someNavigationService.setBackClicked(false);
      // push current state again to prevent further attempts.
      history.pushState(null, null, location.href);
      return false;
    }
    return true;
  }
}
Jithin Nair
  • 841
  • 9
  • 7
  • 1
    `this.someNavigationService.setBackClicked()` what will be definition/implementation of this method? – Vinod Jun 13 '19 at 08:41
  • 1
    @Vinod the method simply updates a flag to true or false per the param sent. The service basically carries a setter and getter for the flag that tells you whether back button was clicked. You set it to true on the click of back/fwd button, and then reset to false once you've handled it. – Jithin Nair Jun 19 '19 at 14:41
  • @JithinNair Please write the code for SomeNavigationService as well. – Rijo Apr 01 '20 at 13:53
  • I have found best from here, https://blog.aakashgoplani.in/disabling-browser-back-navigation-in-angular – Naresh Etikyala Feb 28 '23 at 02:08
16
import { LocationStrategy } from '@angular/common';
constructor( private location: LocationStrategy){  
// preventing back button in browser implemented by "Samba Siva"  
 history.pushState(null, null, window.location.href);  
this.location.onPopState(() => {
  history.pushState(null, null, window.location.href);
});  
}

its working fine to me 100% in angular2/4/5

10

This Very simple, use the following code, This example code is from plain javascript i have converted this into angular and using in my 2-3 projects

// Inject LocationStrategy Service into your component
    constructor(
        private locationStrategy: LocationStrategy
      ) { }


// Define a function to handle back button and use anywhere
    preventBackButton() {
        history.pushState(null, null, location.href);
        this.locationStrategy.onPopState(() => {
          history.pushState(null, null, location.href);
        })
      }

You can define preventBackButton in any service as well and call it from there

Nishant Singh
  • 1,016
  • 12
  • 15
  • This causes lots of errors on Safari: "Attempt to use history.pushState() more than 100 times per 30.000000 seconds" – smee May 01 '20 at 14:07
  • There might be some code that is running repeatedly. I'm not sure what could be the exact cause. Can you paste code here that is causing this error or some screenshot of the error. – Nishant Singh May 02 '20 at 12:50
6

I've tried all the solutions mentioned above but none of them worked perfectly for me.

Finally, after two days of failed attempts, I've found this npm module that worked immediately and perfectly.

Github: https://github.com/Zatikyan/angular-disable-browser-back-button#readme

nicolapiccoli
  • 115
  • 4
  • 10
  • Hi, can it disable mobile back bottom navigation button actions? – syed Aug 02 '23 at 08:31
  • @syed Actually I never tried it for this specific case. Anyway I guess it's only for browser so, if you mean i.e. the back button of an Android phone, I suppose it won't work. – nicolapiccoli Aug 02 '23 at 11:48
  • It is working fine with Android mobile back button, but for IOS it is taking the last clicked event when pressing mobile back button. If I get the resolution for IOS surely will update here. – syed Aug 04 '23 at 07:05
6

Snippet that I use and works across all major browsers!

ngOnInit() {
   history.pushState(null, null, location.href);

   this.subscription = fromEvent(window, 'popstate').subscribe(_ => {
      history.pushState(null, null, location.href);
      this.openModal(`You can't make changes or go back at this time.`, 'Okay');
   });
}

ngOnDestroy() {
   this.subscription.unsubscribe();
}
Ghazni
  • 826
  • 8
  • 16
Aakash Goplani
  • 1,150
  • 1
  • 19
  • 36
2

A bit late perhaps but maybe somebody can use it. This is a solution I use for a page with tabs (Bootstrap 4 style) where each tab is a component.

    @Injectable()
    export class CanNavigateService {

      private static _isPermissionGranted = true
      public navigationAttempt = new Subject<boolean>()

      //-------------------------------------------------------------//

      /**Will the next navigation attempt be permitted? */
      updatePermission(isPermissionGranted: boolean) {   
        CanNavigateService._isPermissionGranted = isPermissionGranted
      }//updatePermission

      //-------------------------------------------------------------//

      /**Broadcast the last attempt and whether it was permitted */
      updateNavigationAttempt(wasPermissionGranted: boolean) {    
        this.navigationAttempt.next(wasPermissionGranted)
      }//updatePermission

      //-------------------------------------------------------------//

      /**Can we navigate? */
      public isPermissionGranted(): boolean {
        return CanNavigateService._isPermissionGranted
      }//isPermissionGranted

    }//Cls

NavigationGuard like @Jithin Nair above but also broadcasts when an attempt to navigate was made and whether it was permitted. Subscribers of CanNavigateService can use it to decide what to do instead of back navigation.

@Injectable()
export class NavigationGuard implements CanDeactivate<any> {

constructor(private canNavigateService: CanNavigateService) { }

//--------------------------------------------------------------------//

// will prevent user from going back if permission has not been granted
canDeactivate(component: any) {

    let permitted = this.canNavigateService.isPermissionGranted()
    this.canNavigateService.updateNavigationAttempt(permitted)        

    if (!permitted) {
        // push current state again to prevent further attempts.
        history.pushState(null, null, location.href)
        return false
    }

    return true

}//canDeactivate

}//Cls

Usage:

constructor(private _navigateService: CanNavigateService) {
    super()

    _navigateService.navigationAttempt.subscribe(wasPermitted => {
        //If navigation was prevented then just go to first tab
        if (!wasPermitted)
           this.onTabSelected( this._firstTab)            
    })
}//ctor

//----------------------------------------------------------------------------//

onTabSelected(tab) {

    this._selectedTab = tab
    //If it's not the first tab you can't back navigate
    this._navigateService.updatePermission(this._selectedTab == this._firstTab)
}//onTabSelected
ShanieMoonlight
  • 1,623
  • 3
  • 17
  • 28
1

If you want to prevent a route to be reached you can add the @CanActivate() decorator to your routing component

@Component({selector: 'control-panel-cmp', template: `<div>Settings: ...</div>`})
@CanActivate(checkIfWeHavePermission)
class ControlPanelCmp {
}

See also
- Angular 2: Inject a dependency into @CanActivate? for access to global services.
- Angular2 Router - Anyone know how to use canActivate in app.ts so that I can redirect to home page if not logged in

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
1

Try this

<script type = "text/javascript" >
history.pushState(null, null, 'pagename');
window.addEventListener('popstate', function(event) {
history.pushState(null, null, 'pagename');
});
</script>

where change 'pagename' to your page name and put this into head section of page.

Vishal Rajole
  • 1,504
  • 1
  • 13
  • 19
1

try to use this

window.onpopstate = function (e) { window.history.forward(1); }
buddemat
  • 4,552
  • 14
  • 29
  • 49
Farouk Mhamdi
  • 311
  • 2
  • 8
  • Interesting vanilla-JS solution, although _Angular2+_ was asked. Can you __please explain your solution__ or add a link to documentation like: [WindowEventHandlers.onpopstate - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate) – hc_dev Mar 04 '21 at 19:24
  • This is a bad "solution". Basically, it go back, and just after, go forward, loosing your data in the process. – Cocorico Jul 06 '23 at 08:14
1

Why not use just this. Should avoid browser insert automatically things in the history. Just insert in some main.ts (or elsewhere executed at startup)

   history.pushState = () => {}; 
   Object.freeze(history);
G.D.
  • 75
  • 9
0

This issue occurs on IE browser. Use below mentioned code it will resolve your issue.


        @HostListener('document:keydown', ['$event'])
          onKeyDown(evt: KeyboardEvent) {
            if (
                evt.keyCode === 8 || evt.which === 8
            ) {
              let doPrevent = true;
              const types =['text','password','file','search','email','number','date','color','datetime','datetime-local','month','range','search','tel','time','url','week'];
              const target = (<HTMLInputElement>evt.target);

          const disabled = target.disabled || (<HTMLInputElement>event.target).readOnly;
          if (!disabled) {
            if (target.isContentEditable) {
              doPrevent = false;
            } else if (target.nodeName === 'INPUT') {
              let type = target.type;
              if (type) {
                type = type.toLowerCase();
              }
              if (types.indexOf(type) > -1) {
                doPrevent = false;
              }
            } else if (target.nodeName === 'TEXTAREA') {
              doPrevent = false;
            }
          }


        if (doPrevent) {
            evt.preventDefault();
            return false;
          }

        }
    }

Vijay Gawade
  • 94
  • 1
  • 3
0

If you are looking to disable browser back button in angular(7/8/9/10)... Try this link and install package using npm.

1) npm install --save angular-disable-browser-back-button
2) import { NgModule } from '@angular/core';
import { BackButtonDisableModule } from 'angular-disable-browser-back-button';
 
@NgModule({
  ...
  imports: [
    ...
    BackButtonDisableModule.forRoot()
  ],
  ...
})
export class AppModule {}

3)  BackButtonDisableModule.forRoot({
      preserveScrollPosition: true
    })

Please use this link given below.. reference taken from.

Link to the lib : https://www.npmjs.com/package/angular-disable-browser-back-button

Cocorico
  • 1,998
  • 1
  • 22
  • 38
SHUBHASIS MAHATA
  • 873
  • 7
  • 12
-1

This isn't Angular2 related problem. You can send the user back in history. See Manipulating the browser history, history.go() method particular:

window.history.go(-1);

However, I don't think there's a way to cancel or disable default browser action on pressing back button in the browser window because that could be very easily abused.

As an alternative you can show a dialog window when user tries to leave the page: javascript before leaving the page

Community
  • 1
  • 1
martin
  • 93,354
  • 25
  • 191
  • 226
-1

Add following code in TS file of the component, where you don't want to go back.

  @HostListener('window:hashchange', ['$event'])
  hashChangeHandler(e) {
    window.location.hash = "dontgoback";
  }
Charlie
  • 4,827
  • 2
  • 31
  • 55
-2

step 1: Import Locatoion from angular commmon

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

step 2: Initialise in constructor

private location: Location

step 3: Add function in ngOnInit of the respective coponent,

this.location.subscribe(currentLocation => {
if (currentLocation.url === '*/basic-info*') {
    window.onpopstate = function (event) {
        history.go(1);
    }
}

});

Note: Here /basic-info will be replaced by your path.

If first time it is not working, try adding outside subscribe,

let currentUrl = window.location.href;
let tmpVar = currentUrl.includes('/basic-info');
if (currentUrl.includes('/basic-info')) {
  window.onpopstate = function (event) {
    history.go(1);
  }
}
Community
  • 1
  • 1
saravana va
  • 1,081
  • 1
  • 13
  • 17