I'm trying to select two fields from the ngrx store in an Angular Guard like this:
@Injectable()
export class RoleGuard implements CanActivate {
constructor(
public router: ActivatedRouteSnapshot,
private store: Store<AppState> ) {}
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
const expectedRole = route.data.Role;
return combineLatest(
this.store.pipe(select(isLoggedIn)),
this.store.pipe(select(currentUser)),
).pipe(
tap( ([loggedIn, user]) =>
{
if ( loggedIn && !(user.role.find(expectedRole) >= 0) ) {
this.router.navigateByUrl('/error/403')
};
}
)
);
}
}
However, I'm getting Type 'boolean | [any, any]' is not assignable to type 'boolean'
, which makes sense, since the combineLatest return the result in array. But I can't seem to find a more elegant way than combineLatest, instead of nesting the two select observable, what would be my alternatives here?
canActivate
method should return a boolean
wrapped in an Observable
. As per your code, it is returning the values wrapped in an Observable
returned from the combineLatest
method which is an array. You can use map
operator to return true
or false
like this:
@Injectable()
export class RoleGuard implements CanActivate {
constructor(
public router: ActivatedRouteSnapshot,
private store: Store<AppState> ) {}
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
const expectedRole = route.data.Role;
return combineLatest(
this.store.pipe(select(isLoggedIn)),
this.store.pipe(select(currentUser)),
).pipe(
map( ([loggedIn, user]) =>
{
if ( loggedIn && !(user.role.find(expectedRole) >= 0) ) {
this.router.navigateByUrl('/error/403')
//I am assuming that you want to fail the guard and want your application to route to 403 page, so let’s return false
return false;
};
//I am assuming that you want to pass the guard of above if condition fails, so return true; bottom line is to return true/false as per your logic.
return true;
}
)
);
}
}
Hope it helps.