I have a big problem and after hours of reading documents and solution I can't find how I will be able to solve this problem :
Basically I have in my angular guard this :
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.checkLogin(route);
}
checkLogin(route) {
return this.authService.login().map(response => {
if (this.authService.isAuth) {
return this.authService.grants().map(grants => {
if (grants.canRead) {
return true;
}
})
}
});
}
What I want to do is first to call the service authService.login, and if I'm authentified then I call the authService.grants to check if the user can read this page or not.
As simple as that but I'm not being able to get into the second call I don't know why it's returning an observable.
Without having the definitions of your methods, Ill assume the following:
interface Rights {
canRead: boolean;
}
class AuthService {
grants(): Observable<Rights>{}
login(): Observable<any>{}
}
The problem is, that currently the return type of your checkLogin
method is Observable<boolean>| Observable<Observable<boolean>>
. This is because:
this.authService.isAuth
is false
, the outer map will yield a Observable<boolean>
, as you simply return false
.this.authService.isAuth
is true
, the outer map will yield a Obsevable<Observable<boolean>>
, as you will now return the mapped values of another async. operation.So using that, you should refactor your guard to the following:
import 'rxjs/add/operator/mergeMap'; // can be refactored to pipe + operator
import {of} from 'rxjs/observable/of';
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.checkLogin(route);
}
checkLogin(route): Observable<boolean> {
return this.authService.login().mergeMap(_=> {
if (this.authService.isAuth) {
return this.authService.grants().map(grants => grants.canRead)
}else{
return of(false);
}
});
}
}
MergeMap is basically allowing you to concatenate asynchronous operations, and of creates an observable of a sync. value.