Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 - Routing - CanActivate work with Observable

I have an AuthGuard (used for routing) that implements CanActivate.

canActivate() {     return this.loginService.isLoggedIn(); } 

My problem is, that the CanActivate-result depends on a http-get-result - the LoginService returns an Observable.

isLoggedIn():Observable<boolean> {     return this.http.get(ApiResources.LOGON).map(response => response.ok); } 

How can i bring those together - make CanActivate depend on a backend state?

# # # # # #

EDIT: Please note, that this question is from 2016 - a very early stage of angular/router has been used.

# # # # # #

like image 585
Philipp Avatar asked Jun 21 '16 15:06

Philipp


People also ask

How does CanActivate work in Angular?

The canActivate method returns a boolean indicating whether or not navigation to a route should be allowed. If the user isn't authenticated, they are re-routed to some other place, in this case a route called /login . Now the guard can be applied to any routes you wish to protect.

What is the difference between CanActivate and CanActivateChild?

In my view, the CanActivate is used to restrict access from a certain path and all the sub-paths and CanActivateChild is used to restrict access to a specific group inside the CanActivate path.

What is the difference between CanActivate and CanDeactivate?

CanActivate : Checks route navigation before the component is loaded. CanActivateChild : Checks route children navigation before the component is loaded. CanDeactivate : Checks navigation from the current route eg leaving the partially filled form. Resolve : Resolve loads/ retrieves data before the route is activated.


2 Answers

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!

like image 58
Kery Hu Avatar answered Oct 16 '22 07:10

Kery Hu


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);       })     );   }       } 
like image 26
Derek Hill Avatar answered Oct 16 '22 07:10

Derek Hill