Get the value returned by canActivate Method in Angular2 Route in a component?

2.1k views Asked by At

I have created a Auth Manager in Angular2 to restrict Component access directly . I am still new to angular and learning the concepts.

I was able to restrict the user if the user name is not correct. But i am not able to use the value returned by the canActivate Method in my component to display a message in my front end.

My AuthManager class

import { Injectable } from '@angular/core';
import { CanActivate,Router,ActivatedRouteSnapshot,RouterStateSnapshot } from '@angular/router';

@Injectable()

export class AuthManager implements CanActivate{

    user = "user";

    constructor(private router:Router){

    }

    canActivate(route:ActivatedRouteSnapshot,state:RouterStateSnapshot){
        console.log("Comes Here");
            if(this.user == "user"){
                return true;
            }else{
                console.log("YOur are not authorized");
                this.router.navigate(['/persons']);
                return false;
            }
    }
}

I am able to see YOur are not authorized in log but how to use the value in a component.

My app.router.ts

{
    path: 'persons/:id',
    component: PersonDetailComponent,
    canActivate:[AuthManager]       
    }
3

There are 3 answers

0
Rahul Singh On

What i understood by the Question is that you want to display Some kind of Error Message to the User if the Auth Fails. @PierreDuc is correct.But i have a different approach to this.

what you can do is create a service class

authenticate.service.ts

import {Injectable} from '@angular/core'

@Injectable()

export class AuthenticateService

    isAuthenticated(//take the user credentials here):boolean{
        return true // if the credentials are correct 

     or retun false // if the credentials donot match.    

    }

make use of this class in your component and AuthManager

import { Injectable } from '@angular/core';
import { CanActivate,Router,ActivatedRouteSnapshot,RouterStateSnapshot } from '@angular/router';
import {AuthenticateService} from './authenticate.service'

@Injectable()

export class AuthManager implements CanActivate{

    user = "user";

    constructor(private router:Router,private authenticateService:AuthenticateService){

    }

    canActivate(route:ActivatedRouteSnapshot,state:RouterStateSnapshot){
        console.log("Comes Here");
           return  this.authenticateService.isAuthenticated();
    }
}

and in the component check the same

this.authenticateService.isAuthenticated()== false
*ngIf and then display an error message to the user.

Hope this is what you where looking at . it not exactly the answer of the question but a way to solve your problem.

1
Sudheer KB On

You can use service and set the value you want to display in component inside the AuthManager.

6
Poul Kruijt On

That's quite an uncommon thing to do, but I understand why you would want something like that. It is however not possible to capture the result returned from CanActivate.

However you could make an ErrorService and subscribe a component to an triggered event to show a toast message or something like that.

untested code ahead

@Injectable()
export class AuthManager implements CanActivate{

    user = "user";

    constructor(private router:Router, private errorService: ErrorService){}

    canActivate(route:ActivatedRouteSnapshot,state:RouterStateSnapshot){
       if(this.user == "user"){
            return true;
       } else{
           this.errorService.toastError("You are not authorized");
           this.router.navigate(['/persons']);
           return false;
       }
    }
}

Your error service would in basic look something like this, you should add this service to your root providers:

export class ErrorService {

   public readonly error: Subject<string> = new Subject<string>(); 

   public toastError(error: string): void {
     this.error.next(error);
   }

}

After that place a component inside your AppComponent (or whatever you deem fit) and make it something like this:

@Component({
   selector : 'error-toast',
   template : `<div [innerHtml]="error" *ngIf="error"></div>`
})
export class ErrorToastComponent implements OnInit, OnDestroy { 

   public error: string = "";  

   private timeout: number = 0;

   private errorSub: Subscription;

   private readonly timer: number = 5000;

   constructor(private errorService: ErrorService) {}

   ngOnInit(): void {
      this.errorSub = this.errorService.subscribe((error: string) => {
          this.toastError(error);
      });
   }

   ngOnDestroy(): void {
      this.errorSub.unsubscribe();
      this.cancelTimer();
   }

   private toastError(error): void {
      this.cancelTimer();
      this.error = error;
      this.timeout = window.setTimeout(() => {
         this.error = "";
      }, this.timer);
   }

   private cancelTimer(): void {
      if(this.timeout !== 0) {
         clearTimeout(this.timeout);
         this.timeout = 0;
      }
   }

}