Passa al contenuto principale

Functional Guards e Resolvers

I guard e resolver vanno implementati come funzioni, non come classi.

Guard

import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';

export const authGuard: CanActivateFn = () => {
const auth = inject(AuthService);
const router = inject(Router);

if (auth.isLoggedIn()) {
return true;
}
return router.createUrlTree(['/login']);
};

export const roleGuard: CanActivateFn = (route) => {
const auth = inject(AuthService);
const requiredRole = route.data['role'] as string;
return auth.hasRole(requiredRole);
};

Registrazione nelle route

export const routes: Routes = [
{
path: 'admin',
canActivate: [authGuard, roleGuard],
data: { role: 'admin' },
loadComponent: () => import('./admin.component').then(m => m.AdminComponent)
}
];

Resolver

import { ResolveFn } from '@angular/router';

export const userResolver: ResolveFn<User> = (route) => {
const userService = inject(UserService);
return userService.getById(route.params['id']);
};
{
path: 'users/:id',
resolve: { user: userResolver },
loadComponent: () => import('./user-detail.component').then(m => m.UserDetailComponent)
}

Accesso al dato risolto nel componente

@Component({ ... })
export class UserDetailComponent {
private readonly route = inject(ActivatedRoute);
readonly user = toSignal(this.route.data.pipe(map(d => d['user'] as User)));
}

Composizione di guard

export function hasAnyRole(...roles: string[]): CanActivateFn {
return () => {
const auth = inject(AuthService);
return roles.some(role => auth.hasRole(role));
};
}

// Uso
canActivate: [authGuard, hasAnyRole('admin', 'editor')]