Skip to content

Generate Angular Component

Create a new Angular standalone component named $ARGUMENTS.

Requirements

  1. Read the project's CLAUDE.md for conventions, folder structure, and selector prefix.

  2. Determine the component type:

    • Page (container/smart component): Manages state, injects services, handles routing. Place under pages/.
    • View (presentational/dumb component): Receives data via input(), emits events via output(), no service injection. Place under views/.
    • If --type is not specified, infer from the name or ask.
  3. Determine the target directory:

    Standard Angular CLI project:

    • If --feature <name> is provided, place under src/app/features/<name>/components/pages/ or views/.
    • If the name suggests a shared component, place under src/app/shared/components/.
    • Otherwise, ask where to place it.

    Nx monorepo project:

    • If --feature <name> is provided, place under libs/ui/features/<name>/src/lib/components/pages/ or views/.
    • If the component is a reusable UI element, place under libs/ui/component-library/src/components/.
    • If the component belongs to the app shell, place under apps/<app-name>/src/app/components/pages/ or views/.
    • Otherwise, ask where to place it.
  4. Generate these files:

    • <name>.component.ts - Component class
    • <name>.component.html - Template (only if template exceeds ~30 lines, otherwise inline)
    • <name>.component.scss - Styles (only if styles exceed ~10 lines, otherwise inline)
    • <name>.component.spec.ts - Unit tests

Component Conventions

Apply all of the following:

typescript
@Component({
  selector: '<prefix>-<name>',  // Use the selector prefix from CLAUDE.md
  standalone: true,
  imports: [/* only what's needed */],
  changeDetection: ChangeDetectionStrategy.OnPush,
  // inline template if short, otherwise templateUrl
  template: `...`
})
  • Use input() and output() functions for data flow
  • Use computed() for derived state
  • Use @if, @for, @switch control flow (never *ngIf, *ngFor)
  • Always include track in @for blocks
  • Use inject() for dependencies (page components only; views should not inject services)
  • Use class and style bindings (not ngClass/ngStyle)
  • Add accessibility attributes (ARIA labels, roles) where appropriate
  • If the project uses Tailwind CSS, use utility classes for styling instead of custom SCSS

Page Component Pattern

typescript
@Component({
  selector: '<prefix>-<name>-page',
  standalone: true,
  imports: [NameViewComponent],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <prefix-name-view
      [data]="data()"
      (action)="onAction($event)"
    />
  `
})
export class NamePageComponent {
  private readonly service = inject(NameService);
  readonly data = this.service.data;

  onAction(event: ActionEvent): void {
    this.service.handleAction(event);
  }
}

View Component Pattern

typescript
@Component({
  selector: '<prefix>-<name>-view',
  standalone: true,
  imports: [],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    @if (data(); as d) {
      <div>&#123;&#123; d.name &#125;&#125;</div>
    }
  `
})
export class NameViewComponent {
  data = input.required<DataType>();
  action = output<ActionEvent>();
}

Test Conventions

typescript
describe('ComponentName', () => {
  let fixture: ComponentFixture<ComponentName>;
  let component: ComponentName;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [ComponentName],
      // provide mocks for injected services (page components only)
    }).compileComponents();

    fixture = TestBed.createComponent(ComponentName);
    component = fixture.componentInstance;
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  // Test input/output behavior
  // Test template rendering with @if/@for
  // Test user interactions
});

Output

After generating, summarize:

  • Files created and their locations
  • Component type (page or view)
  • Inputs and outputs of the component
  • Any dependencies added to imports

Copyright © MSG Systems Romania AI Labs