| name | angular-module-setup |
| description | Angular module setup with inject() function, InjectionToken for repository ports, route-level providers for DI scoping, lazy loading with loadComponent/loadChildren, infrastructure providers array, and functional guards. Use when configuring DI, creating tokens, wiring providers, setting up routes, or understanding injection scope. |
Angular Module Setup — DI + Routing
inject() Function
All DI uses inject() function. Never constructor injection.
private readonly http = inject(HttpClient);
private readonly destroyRef = inject(DestroyRef);
private readonly repository = inject(ENTITY_REPOSITORY);
private readonly dialogControl = inject(DialogControl, { optional: true });
InjectionToken for Repository Ports
Domain layer defines the port + token:
import { InjectionToken } from '@angular/core';
export interface EntityRepository {
find(params: FilterParams): Promise<Result<PagedResult<Entity>>>;
create(params: CreateParams): Promise<Result<Entity>>;
update(params: UpdateParams): Promise<Result<Entity>>;
delete(id: EntityId): Promise<Result<void>>;
}
export const ENTITY_REPOSITORY = new InjectionToken<EntityRepository>('EntityRepository');
Route-Level Providers
Providers registered at route level, NOT component or root:
export const entityRoutes: Routes = [
{
path: '',
loadComponent: () => import('./pages/entity-page.component').then(m => m.EntityPageComponent),
providers: [...EntityInfrastructureProviders],
},
];
Infrastructure Providers Array
export const EntityInfrastructureProviders: Provider[] = [
GetEntitiesQuery,
CreateEntityUseCase, UpdateEntityUseCase, DeleteEntityUseCase,
EntityApiClient,
{ provide: ENTITY_REPOSITORY, useClass: EntityRepositoryImpl },
];
Order: Queries → UseCases → API Clients → Repository implementations
Lazy Loading
{ path: 'entities', loadComponent: () => import('@app/entity').then(m => m.EntityPageComponent) }
{ path: 'entities', loadChildren: () => import('@app/entity').then(m => m.entityRoutes) }
Route Params as Signal Inputs
provideRouter(routes, withComponentInputBinding());
entityId = input<string>();
Functional Guards
export const authGuard: CanActivateFn = () => {
const auth = inject(AuthService);
return auth.isAuthenticated() || inject(Router).createUrlTree(['/login']);
};
DestroyRef — Always Inject Explicitly
private readonly destroyRef = inject(DestroyRef);
stream$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe();
State Services — Component-Level Providers
@Component({
providers: [EntityListStateService],
})
export class EntityPageComponent {
readonly state = inject(EntityListStateService);
}
For detailed patterns, see references/di-patterns.md.