Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent backward navigation in angular app (mobile)

I need to prevent the user from backward navigation in some parts of an app I am building. So far I am using this method:

ngOnInit() { 

 history.pushState(null, null, location.href);   
 window.onpopstate = function(event) {
   history.go(1);
 };
}

ngOnDestroy() {
 window.onpopstate = function(event) {
   history.go();
 };
}

This is working great except on iOS chrome and safari. I've also tried:

history.replaceState(null, document.title, location.pathname);

in ngOnInit with not luck. Can someone enlighten my on how browsers on these mobile devices are using history and/or popstate differently than on windows/macOS versions of browsers?

like image 424
Anthony Avatar asked Nov 10 '17 15:11

Anthony


Video Answer


1 Answers

Instead of trying to implement different browser-specific solutions, I would think about Angular's CanDeactivate guard.

Suppose you have a service (let's call it NavigatorService) that always stores the previous route:

@Injectable()
export class NavigatorService{
  private previousRoute:string = null;
  private currentRoute:string = null;
  /** Listen to and log new route paths */
  constructor(private router:Router){
    router.events.filter(e => e instanceof NavigationEnd).subscribe(
      e => {
        this.previousRoute = this.currentRoute;
        this.currentRoute = e['url'];
      }
    )
  }
  /** Checks whether the next route corresponds to the previous route  */
  isGoingBack(nextState:RouterStateSnapshot){                   
      return nextState.url === this.previousRoute;
  }
}

Next create a CanDeactivateGuard that will rely on this service to determine whether to allow the user to navigate away from the current view:

@Injectable()
export class BackwardGuard implements CanDeactivate<any> {
  // Inject the service needed
  constructor(navigatorService:NavigatorService){}

  // Angular 4 provides these arguments to any CanDeactivate guard
  // see https://angular.io/api/router/CanDeactivate#interface-overview
  canDeactivate(component:any, currentRoute:ActivatedRouteSnapshot, 
             currentState:RouterStateSnapshot, nextState:RouterStateSnapshot){                   
      // Allow navigation only if the user is not going back
      return !this.navigatorService.isGoingBack(nextState);
  }
}

Finally, register this guard on the routes whose components you want to protect from backwards navigation:

appRoutes:Routes = [
  {
    path: 'some-path',
    component: ProtectedComponent,
    canDeactivate: [BackwardGuard]
  }
];

There may be bugs in this untested code, but I think once you iron them out, it should work. Remember to provide NavigatorService to your component's module (e.g: AppModule) and to provide BackwardGuard to the matching routing module (e.g.: AppRoutingModule)

like image 154
BeetleJuice Avatar answered Sep 28 '22 22:09

BeetleJuice