Angular 2 - Routing - CanActivate work with Observable
You should upgrade "@angular/router" to the latest . e.g."3.0.0-alpha.8"
modify AuthGuard.ts
@Injectable()export class AuthGuard implements CanActivate { constructor(private loginService: LoginService, private router: Router) {} canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) { return this.loginService .isLoggedIn() .map((e) => { if (e) { return true; } }) .catch(() => { this.router.navigate(['/login']); return Observable.of(false); }); }}
If you have any questions, ask me!
Updating Kery Hu's answer for Angular 5+ and RxJS 5.5 where the catch
operator is deprecated. You should now use the catchError operator in conjunction with pipe and lettable operators.
import { Injectable } from '@angular/core';import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';import { Observable } from 'rxjs/Observable';import { catchError, map} from 'rxjs/operators';import { of } from 'rxjs/observable/of';@Injectable()export class AuthGuard implements CanActivate { constructor(private loginService: LoginService, private router: Router) { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> { return this.loginService.isLoggedIn().pipe( map(e => { if (e) { return true; } else { ... } }), catchError((err) => { this.router.navigate(['/login']); return of(false); }) ); } }
canActivate() accepts Observable<boolean>
as returned value. The guard will wait for the Observable to resolve and look at the value. If 'true' it will pass the check, else ( any other data or thrown error ) will reject the route.
You can use the .map
operator to transform the Observable<Response>
to Observable<boolean>
like so:
canActivate(){ return this.http.login().map((res: Response)=>{ if ( res.status === 200 ) return true; return false; });}