Angular’s “CanActivate” interface is deprecated. How to replace it?

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.

Leave a Comment