I need to inject a service in a guard. This guard checks if the user was invited, when yes, he can access the route.
To check this condition, I need to call a service which fetches this information from the db.
I have a cyclical dependency error, I understand that we shouldn't inject services in Guards, but in this case, I need to do it:
providers: [AuthService, HackService, HacksStorageService, AuthGuard, EmailGuard],
And the guard:
import { ActivatedRouteSnapshot, RouterStateSnapshot, CanActivate } from "../../../node_modules/@angular/router";
import { HacksStorageService } from "../shared/hacks-storage.service";
export class EmailGuard implements CanActivate {
constructor(
private hacksStorageService: HacksStorageService,
) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
this.hacksStorageService.fetchHack();
// check if user was invited. should be in the participants array
return true;
}
}
I am pretty confused. Usually I used guards to see if user is logged in or not, so I usually imported stuff from firebase, not from my own services, so not cyclical dependencies.
Now I want to check if a condition happens, based on my own data. How can I inject my own data in the EmailGuard, if I am not allowed to inject services because of the cyclical dependency?
Thanks.
You can inject services in guards. If your service returns synchronously, then you can just return immediately, like in your sample code. Otherwise, I did it like this (using firebase auth)
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { Observable, of } from 'rxjs';
import { map, first } from 'rxjs/operators';
import { AngularFireAuth } from '@angular/fire/auth';
import { Paths } from './paths';
@Injectable({
providedIn: 'root'
})
export class SignInGuard implements CanActivate {
constructor(private afAuth: AngularFireAuth, private router: Router) { }
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
return this.afAuth.user.pipe(
first(),
map(user => {
if (user) {
this.router.navigate([Paths.MAIN_PATH]);
return false;
} else {
return true;
}
})
);
}
}