Angular module setup
Skill cuongtl1992/vibe-skills/skills/frontend/angular-module-setup
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.From its SKILL.md
npx -y skills add cuongtl1992/vibe-skills --skill angular-module-setupAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 11 stars11 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
3.2 KB, as published. Nobody here has run it
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[] = [
// Queries (Application Layer)
GetEntitiesQuery,
// Use Cases (Application Layer)
CreateEntityUseCase, UpdateEntityUseCase, DeleteEntityUseCase,
// API Clients (Infrastructure Layer)
EntityApiClient,
// Repository Implementations (Adapters)
{ provide: ENTITY_REPOSITORY, useClass: EntityRepositoryImpl },
];
Order: Queries → UseCases → API Clients → Repository implementations
Lazy Loading
// Single component
{ path: 'entities', loadComponent: () => import('@app/entity').then(m => m.EntityPageComponent) }
// Child routes with shared providers
{ path: 'entities', loadChildren: () => import('@app/entity').then(m => m.entityRoutes) }
Route Params as Signal Inputs
// app.config.ts
provideRouter(routes, withComponentInputBinding());
// component
entityId = input<string>(); // auto-bound from :entityId route param
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);
// In ngOnInit — MUST pass 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.