Generate Angular Component
Create a new Angular standalone component named $ARGUMENTS.
Requirements
Read the project's
CLAUDE.mdfor conventions, folder structure, and selector prefix.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 viaoutput(), no service injection. Place underviews/. - If
--typeis not specified, infer from the name or ask.
- Page (container/smart component): Manages state, injects services, handles routing. Place under
Determine the target directory:
Standard Angular CLI project:
- If
--feature <name>is provided, place undersrc/app/features/<name>/components/pages/orviews/. - 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 underlibs/ui/features/<name>/src/lib/components/pages/orviews/. - 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/orviews/. - Otherwise, ask where to place it.
- If
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()andoutput()functions for data flow - Use
computed()for derived state - Use
@if,@for,@switchcontrol flow (never*ngIf,*ngFor) - Always include
trackin@forblocks - Use
inject()for dependencies (page components only; views should not inject services) - Use
classandstylebindings (notngClass/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>{{ d.name }}</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