I am trying to use one of the Angular v14 features which is CanActivateFn.
Unfortunately, when my guard is executed and the statement in return is false, I am not getting redirected. Error is being thrown:
Uncaught (in promise): TypeError: router.parseUrl is not a function TypeError: router.parseUrl is not a function
allowed-entities.guard.fn.ts
export function AllowedEntitiesGuard(allowedEntities: string[]): CanActivateFn {
const router = Inject(Router);
return (route: ActivatedRouteSnapshot) => {
const entitiesTypeParameter = route.paramMap.get('entitiesType')
return allowedEntities.indexOf(entitiesTypeParameter) !== -1 ? true : router.parseUrl('/');
};
}
main.ts
bootstrapApplication(AppComponent, {
providers: [
provideHttpClient(withInterceptorsFromDi()),
{
provide: HTTP_INTERCEPTORS,
useClass: JwtInterceptor,
multi: true,
},
{ provide: APP_CONFIG, useValue: environment },
provideRouter(APP_ROUTES),
],
});
When I am trying to console.log router, it shows me its function ParamDecorator instance. What I am doing wrong?
The problem was related to wrong import.
I should use inject instead of Inject.
allowed-entities.guard.fn.ts
// Good!
import { inject } from '@angular/core';
// Absolutely wrong!
import { Inject } from '@angular/core';
Another thing. I cannot use inject() like above in the original post, because of NG0203. I had to move Router injection into CanActivateFn body, so it belongs to context.
I ended up with guard looking like that:
allowed-entities.guard.fn.ts
export function AllowedEntitiesGuard(allowedEntities: string[]): CanActivateFn {
return (route: ActivatedRouteSnapshot): boolean | UrlTree => {
const router: Router = inject(Router);
const entitiesType: string | null = route.paramMap.get(
'entitiesType'
);
return allowedEntities.indexOf(entitiesType) !== -1 ? true : router.parseUrl('/');
};
}
With this approach, I can pass the entities directly into the guard. No need to specify additional data parameter and then retrieve it from ActivatedRouteSnapshot.
app.routes.ts
canActivate: [AllowedEntitiesGuard(['EntityTypeOne', 'EntityTypeTwo'])