2
votes

Please help use async route guard.

I have service, which check authentication users:

@Injectable()
export class GlobalVarsService {

    private isAgreeOk = new BehaviorSubject(false);

  constructor() { };

  getAgreeState(): Observable<boolean> {
    return this.isAgreeOk;
  };  

  setAgreeState(state): void {
    this.isAgreeOk.next(state);    
  };   
}

If getAgreeState() return true value, then user is authenticated.

My guard service:

import { GlobalVarsService } from '../services/global-vars.service';


@Injectable()
export class AgreeGuardService implements CanActivate {

  constructor(private router: Router,
                        private globalVarsService: GlobalVarsService) { };

  canActivate() {
    this.globalVarsService.getAgreeState().subscribe(
    state => {
      if(!state) {
            this.router.navigate(['/agree']);
            return false;
      } else {
        return true;
      }      

    }); 
  }  

}

My routes:

const routes: Routes = [
  {
    path: 'agree',
    children: [],
    component: AgreeComponent
  },    
  {
    path: 'question',
    children: [],
    canActivate: [AgreeGuardService],
    component: QuestionComponent
  }, 

But console display follow error message:

ERROR in /home/kalinin/angular2/PRACTICE/feedback/src/app/services/agree-guard.service.ts (8,14): Class 'AgreeGuardService' incorrectly implements interface 'CanActivate'. Types of property 'canActivate' are incompatible. Type '() => void' is not assignable to type '(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => boolean | Observable | Pr...'. Type 'void' is not assignable to type 'boolean | Observable | Promise'.

GlobalVarsService and his methods i use also in other components. therefore I can not change them.

1

1 Answers

4
votes

You cannot return anything from subscribe, use map instead, also you need to add a return statement.

canActivate() {
  // add 'return'
  return this.globalVarsService.getAgreeState()
   // change this!
   // .subscribe(state => {
   .map(state => {
     if(!state) {
        this.router.navigate(['/agree']);
        return false;
     }
     return true;
   }); 
 }