The trick is to rely on inject()
for the injection of the instances you need :
export const canActivate: CanActivateFn = (
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) => {
const authService = inject(AuthenticationService);
const router = inject(Router);
return authService.checkLogin().pipe(
map(() => true),
catchError(() => {
router.navigate(['route-to-fallback-page']);
return of(false);
})
);
};
export const canActivateChild: CanActivateChildFn = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => canActivate(route, state);
inject()
allows you to use the dependency injection when you are in an injection context. For example in a constructor or like here when passing a function to a core Angular feature.
You can also read about it on the depreciation list.
Edit:
Since v16, Angular provides some helper functions to convert classes to functionnal guards like mapToCanActivate
:
@Injectable({providedIn: 'root'})
export class AdminGuard {
canActivate() {
return true;
}
}
const route: Route = {
path: 'admin',
canActivate: mapToCanActivate([AdminGuard]),
};
You can find the others here.