agentsclimarketplace

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

Install
npx -y skills add cuongtl1992/vibe-skills --skill angular-module-setup

Assembled 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.

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.