Is it possible to stop router navigation based on some condition

Angular

Angular Problem Overview


I'm new to angular, I want stop the routing when user clicks on refresh button or back button based on some condition. I don't know whether this is possible, if anybody knows help me

constructor(private route: Router) {
    this.route.events
        .filter(event => event instanceof NavigationEnd)
        .pairwise().subscribe((event) => {
            if (expression === true){
                // stop routing 
            } else {
                // continue routing
            }      
        });
}

Can it be possible? If yes, how can I do this?

Angular Solutions


Solution 1 - Angular

I stumbled upon this question quite a bit after the fact, but I hope to help someone else coming here.

The principal candidate for a solution is a route guard.

See here for an explanation: https://angular.io/guide/router#candeactivate-handling-unsaved-changes

The relevant part (copied almost verbatim) is this implementation:

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

import { MyComponent} from './my-component/my-component.component';

@Injectable({ providedIn: 'root' })
export class CanDeactivateGuard implements CanDeactivate<MyComponent> {

  canDeactivate(
    component: MyComponent,
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> | boolean {
    // you can just return true or false synchronously
    if (expression === true) {
      return true;
    }
    // or, you can also handle the guard asynchronously, e.g.
    // asking the user for confirmation.
    return component.dialogService.confirm('Discard changes?');
  }
}

Where MyComponent is your custom component and CanDeactivateGuard is going to be registered in your AppModule in the providers section and, more importantly, in your routing config in the canDeactivate array property:

{
  path: 'somePath',
  component: MyComponent,
  canDeactivate: [CanDeactivateGuard]
},

Solution 2 - Angular

The easy way for me is with skiplocationchange in a new route navigate like this:

if(condition === true){

  const currentRoute = this.router.routerState;

  this.router.navigateByUrl(currentRoute.snapshot.url, { skipLocationChange: true });
  // this try to go to currentRoute.url but don't change the location.

}else{
  // do nothing;
}

is a no beautiful method but works

Solution 3 - Angular

There is another solution which I invented and it works:

(For lazy people like me who do not want to create guard for handling this)

import { NavigationStart, Router } from '@angular/router';

In constructor:

constructor(private router: Router) {
    router.events.forEach((event) => {
      if (event instanceof NavigationStart) {
        /* write your own condition here */
        if(condition){
          this.router.navigate(['/my-current-route']); 
        }
      }
    });
  }

Hopefully you won't be lazy enough to change '/my-current-route' to your route url.

Solution 4 - Angular

You can use NavigationStart event like the following code snippet.

this.router.events.subscribe( (event: any) => {
   if (event instanceOf NavigationStart) {
      /// Your Logic
   }
})

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGavishiddappa GadagiView Question on Stackoverflow
Solution 1 - AngularA. ChiesaView Answer on Stackoverflow
Solution 2 - AngularJavier LópezView Answer on Stackoverflow
Solution 3 - AngularHari DasView Answer on Stackoverflow
Solution 4 - AngularKAUSHIK PARMARView Answer on Stackoverflow