Standalone components and template control flow
Modern Angular applications are standalone by default. A component declares its own imports and can be lazy-loaded directly.
Component contract
@Component({
selector: 'app-order-row',
imports: [CurrencyPipe],
templateUrl: './order-row.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class OrderRow {
order = input.required<Order>();
selected = output<string>();
}Inputs are data flowing in. Outputs are semantic events flowing out.
Avoid outputs named click; emit business meaning such as
orderOpened.
Template syntax
Use property binding for values, event binding for actions, and
interpolation for text. Prefer Angular's built-in @if,
@for, and @switch control flow. Give
@for a stable track expression derived from identity.
@for (order of orders(); track order.id) {
<app-order-row [order]="order" (selected)="open($event)" />
} @empty {
<p>No matching orders.</p>
}Host and content
Host bindings describe the component's own element. Content projection lets a parent provide controlled regions. View queries should not become a backdoor for mutating arbitrary child DOM.
DOM ownership
Let Angular own rendered DOM. Use template bindings, Renderer2, or post-render hooks for legitimate integration. Direct DOM mutation can break SSR hydration, tests, accessibility, and state consistency.
Smart and focused
Route/feature components coordinate data and user outcomes. Presentational components render explicit inputs and emit actions. Do not enforce a ceremonial split when one cohesive component is clearer.
Feynman check
A component is a small machine with labeled inputs, visible output, and named events. Explain who owns each piece of state on one real page.