One intriguing aspect of your query lies in the way you phrased it:
Is there a method to specify, "proceed only if the
canActivate condition returns false" ?
You also presented the solution in an intuitive manner:
{ path: 'log-in', component: LoginComponent, canActivate: [ !UserLoggedInGuard ] },
This essentially means that you must negate
the outcome of UserLoggedInGuard@canActivate
Let's examine the implementation of the UserLoggedInGuard
:
@Injectable()
export class UserLoggedInGuard implements CanActivate {
constructor(private _authService: AuthService) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return this._authService.isLoggedIn();
}
}
Now let's investigate the approach suggested by @Mike
@Injectable()
export class NegateUserLoggedInGuard implements CanActivate {
constructor(private _authService: AuthService) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return !this._authService.isLoggedIn();
}
}
The idea is sound, but it closely depends on the internal workings of UserLoggedInGuard
. If there are any changes to how UserLoggedInGuard@canActivate
operates, NegateUserLoggedInGuard
will fail.
How can we prevent this issue? By leveraging dependency injection:
@Injectable()
export class NegateUserLoggedInGuard implements CanActivate {
constructor(private _userLoggedInGuard: UserLoggedInGuard) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return !this._userLoggedInGuard.canActivate(route,state);
}
}
This implementation mirrors what you wanted with
canActivate: [ !UserLoggedInGuard ]
And the greatest advantage:
- It is not tightly connected to the inner workings of
UserLoggedInGuard
- Can be extended to manipulate the outcomes of multiple
Guard
classes