From harness-claude
Guides developers to author Angular components with proper inputs, outputs, change detection strategy (OnPush), and lifecycle hooks. Covers signal-based inputs/outputs (Angular 17+).
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:angular-component-patternThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Author Angular components with correct inputs/outputs, change detection strategy, and lifecycle hooks
Author Angular components with correct inputs/outputs, change detection strategy, and lifecycle hooks
Default and OnPush change detection strategiesngOnInit, ngOnDestroy, ngAfterViewInit) correctly@ViewChild or @ContentChild@Component and always set selector, template/templateUrl, and changeDetection.changeDetection: ChangeDetectionStrategy.OnPush for all new components — it prevents unnecessary re-renders and forces explicit data flow.input() signal function (Angular 17+) or @Input() decorator. Prefer signal inputs for new code.output() (Angular 17+) or @EventEmitter with @Output(). Signal outputs compose with effects naturally.OnDestroy (or use DestroyRef) to clean up subscriptions, timers, and manual DOM listeners.@ViewChild to access child component or DOM element references after ngAfterViewInit. Never access them in ngOnInit — they are not yet rendered.ViewEncapsulation.Emulated (the default) unless you have a specific reason to pierce the shadow DOM.import {
ChangeDetectionStrategy,
Component,
input,
output,
computed,
OnDestroy,
} from '@angular/core';
export interface Product {
id: string;
name: string;
price: number;
}
@Component({
selector: 'app-product-card',
template: `
<div class="card">
<h2>{{ product().name }}</h2>
<p>{{ formattedPrice() }}</p>
<button (click)="onAdd()">Add to cart</button>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProductCardComponent implements OnDestroy {
// Signal input — reactive by default
product = input.required<Product>();
// Derived value — recalculates only when product() changes
formattedPrice = computed(() =>
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(
this.product().price
)
);
// Typed output
addToCart = output<Product>();
onAdd(): void {
this.addToCart.emit(this.product());
}
ngOnDestroy(): void {
// Clean up any manual subscriptions here
}
}
Change detection in depth: Angular's default change detection walks the entire component tree on every browser event. OnPush restricts checks to components whose input references have changed, an async pipe resolves, or a signal emits. This makes rendering O(changed subtree) instead of O(entire tree). Adopt it globally by setting it as the default in angular.json under schematics.
Signal inputs vs @Input(): Signal inputs (Angular 17.1+) return a Signal<T> rather than a plain value. This means the input participates in the reactivity graph — computed() and effect() can read it without subscribing to a subject or change detection cycle. Prefer input() for new components; @Input() still works and is required for libraries targeting older Angular versions.
Lifecycle hook order:
ngOnChanges — fires before ngOnInit and on every @Input() changengOnInit — fires once after first ngOnChanges; safe to read inputs but NOT view childrenngAfterViewInit — fires after the component's view and child views are initialized; safe to use @ViewChildngOnDestroy — fires just before the component is removed; clean up subscriptions and effectsViewChild timing pitfall: Accessing a @ViewChild in ngOnInit returns undefined because the view hasn't been created yet. Move that logic to ngAfterViewInit.
Output naming: Angular convention for outputs is camelCase event names without the on prefix in the class, but HTML consumers use (addToCart). Avoid naming outputs with the on prefix in the property name — it creates (onAddToCart) which reads redundantly in templates.
Host bindings: Use host: { '[class.active]': 'isActive()' } in the decorator instead of @HostBinding — it is more declarative and compatible with the component metadata compiler.
https://angular.dev/guide/components
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeProvides expert Angular/TypeScript patterns for standalone components, signals, RxJS, NgRx state management, smart/dumb components, and performance.
Generates Angular code and provides architectural guidance on signals, forms, DI, routing, SSR, accessibility, animations, styling, testing, and CLI tooling.
Provides expertise for modern Angular v20+ apps using Signals, Standalone Components, Zoneless change detection, SSR/Hydration, and reactive patterns. Ideal for new builds and performance optimization.