Job
Job

Reputation: 485

Angular Router don't cancel navigation on blocked route

I've currently got these routes for my Angular app.

const routes: Routes = [
  { path: '', component: DashboardComponent },
  { path: 'login', component: LoginComponent },
  { path: 'upload', component: UploadPictureComponent, canActivate: [AngularFireAuthGuard] },
  { path: 'view', component: ListPictureComponent, canActivate: [AngularFireAuthGuard] },
  { path: '**', component: NotFoundComponent },
];

Current behaviour: If a user is not logged in and goes to route upload or view their route is blocked and won't see anything.

Desired behaviour: If a user goes to any blocked routes I want to show them the NotFoundComponent.

The issue that I can't get around is that Angular cancels a routing event when a route is rejected by a guard.

Upvotes: 0

Views: 1283

Answers (3)

Ashish Ranjan
Ashish Ranjan

Reputation: 12950

I am giving this answer as one of the possible solutions, I wouldn't know if its the best or what's the best practice.

  1. I would keep a constant string which I would use for all my manual fallback path navigation. Maybe something like: const FALLBACK_PATH = 'notfound'. I would keep this in a shared location which I can use in any component I want.

  2. In the AngularFireAuthGuard guard, when the login condition fails, I would do:

     this.router.navigateByUrl(FALLBACK_PATH, { skipLocationChange: true });
     return false;
    

    Note: I am doing the skipLocationChange, because I don't want the faulty path to be shown in the URL, you can have it, or not have it, depends on your requirement. Also, the above code is not tested and just gives you an approach.

Upvotes: 2

Ahmed Abdelfattah
Ahmed Abdelfattah

Reputation: 577

You have to manually redirect to "NotFoundComponent" in case of canActivate return false

  canActivate(): boolean {
    if (!this.auth.isAuthenticated()) {
      this.router.navigate(['login']);
      return false;
    }
    return true;
  }

Upvotes: 0

julianobrasil
julianobrasil

Reputation: 9357

canActivate can currently return the desired URLTree. You can just test for the logged user an redirect him in AngularFireAuthGuard:

constructor(private _authService: AuthService, private _router: Router){}
canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | boolean | UrlTree 
{
    if(this._authService.isLoggedIn) {
      // runs your current authorization logic
    } else {
      // the argument of parse is any string that doesn't represent
      // a real route
      return this._router.parse('go-to-page-not-found');
    }
  }

Upvotes: 0

Related Questions