developer1
developer1

Reputation: 557

Angular guard not redirecting to specific page due to exception

So I'm trying to implement a basic guard:

canActivate(route: ActivatedRouteSnapshot,
          state: RouterStateSnapshot): Observable<boolean> {
return this.userService.isBoardMember().pipe(
  map(data => {
    if (data === false) {
      this.router.navigate(['main']);
      return false;
    }
    return true;
  })
);
}

The isBoardMember method looks like this:

getUserDetails(): Observable<User> {
this.requestUrl = `${configs.bgwssApi}v1/bics/${this.bic}/tcifs/${this.tcif}/users`;
return this.http.get<User>(this.requestUrl).pipe(catchError(this.handleError));
}

isBoardMember(): Observable<boolean> {
return this.getUserDetails().pipe(map(data => {
  return (data.userRole === 'BOARD_MEMBER');
}));
}

handleError method:

  private handleError(e: HttpErrorResponse) {
let errorMessage = '';
if (e.error instanceof ErrorEvent) {
  // Client side error received
  errorMessage = `Error getting user occurred: ${e.error.message}`;
} else {
  // Server side error received
  errorMessage = `Error getting user from server, code: ${e.status}, message: ${e.message}`;
}
console.error(errorMessage);
return throwError(errorMessage);

}

The problem is that when getUserDetails http request returns 404 error(doesn't find the specific user), isBoardMember method doesn't return anything so my guard is not properly redirecting to main page as it should - instead it just loads an empty page with no url. Need some help solving this issue.

Upvotes: 1

Views: 1445

Answers (1)

Poul Kruijt
Poul Kruijt

Reputation: 71911

You should add another catchError, because you are throwing an error on 404 in your handleError method.

It feels like the isBoardMember is the right place for that. If you feel like it should be in the guard, you can add the logic there:

So either in the Service:

isBoardMember(): Observable<boolean> {
  return this.getUserDetails().pipe(
    map(data => data.userRole === 'BOARD_MEMBER'),
    catchError(() => of(false))
  );
}

Or in the guard:

constructor(private userService: UserService, private router: Router) {}

canActivate(): Observable<boolean | UrlTree> {
  return this.userService.isBoardMember().pipe(
    catchError(() => of(false)),
    map(data => data || this.router.createUrlTree(['main']))
  );
}

I'm using createUrlTree because that's the recommended way to do a redirect from a guard

Upvotes: 2

Related Questions