Reputation: 649
Checkout this answer to understand the approach. I am using to the same solution to implement the master guard as I have multiple guards and want to execute them in sequence.
In Master Guard -
return guard.canActivate(this.route, this.state);
The whole function is Specified below:
//Create an instance of the guard and fire canActivate method returning a promise
private activateGuard(guardKey: string): Promise<boolean> {
let guard: Guard1 | Guard2 | Guard3 | Guard4;
switch (guardKey) {
case GUARDS.GUARD1:
guard = new Guard1();
break;
case GUARDS.GUARD2:
guard = new Guard2();
break;
case GUARDS.GUARD3:
guard = new Guard3();
break;
case GUARDS.GUARD4:
guard = new Guard4(this._Guard4DependencyService);
break;
default:
break;
}
return guard.canActivate(this.route, this.state);
}
I am getting the error mentioned below:
Type 'boolean | Observable<boolean>' is not assignable to type 'boolean'.
Type 'Observable<boolean>' is not assignable to type 'boolean'.
Please find stackblitz link for the same
Screenshot shared below:
Please share your solution to get rid of this error.
Any help is appreciated thanks in advance!
Upvotes: 0
Views: 3240
Reputation: 3171
As per the stackblitz code shared, the guard
is defined as:
let guard: Guard1 | Guard2;
So guard can be either of the type Guard1
or Guard2
, and each of those classes have a different canActivate
method return type. One has return type Observable<boolean>
, while another has Promise<boolean>
.
The return guard.canActivate(this.route, this.state);
statement can either return Observable<boolean>
or Promise<boolean>
, whereas the function containing the return statement is defined to return Promise<boolean>
.
Do you really need canActivate
method of Guard1
and Guard2
class to have different return types? If you can keep the return type consistent, then that should resolve the issue.
In case if your requirement is still to have different return types, then in case when guard is assigned to Guard2
instance, the return statement should be as:
return guard.canActivate(this.route, this.state).toPromise();
Upvotes: 1
Reputation: 1843
I see your issue now. guard1 service and guard2 service are having two different return types. You need to have both return type as Promise<boolean>
as per MasterGuard service code.
If you see activateGuard() in MasterGuard service then it is expecting for Promise<boolean>
. However, in guard1 service, you have returned Observable<boolean>
.
guard1.service.ts :
@Injectable()
export class Guard1 implements CanActivate, CanActivateChild {
constructor(private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
console.log('Chain-1');
return Promise.resolve(true) // Modified this part
}
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
return this.canActivate(route, state);
}
}
guard2.service.ts :
@Injectable()
export class Guard2 implements CanActivate, CanActivateChild {
constructor() {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
console.log('Chain-2');
return Promise.resolve(true);
}
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
return this.canActivate(route, state);
}
}
Working code: https://stackblitz.com/edit/angular-route-guards-9tzxmv
Issue was because of this line:
switch (guardKey) {
case GUARDS.GUARD1:
guard = new Guard1(this._Router); // because of this line it was creating issue
break;
case GUARDS.GUARD2:
guard = new Guard2();
break;
default:
break;
}
Upvotes: 1