Components and templates
Standalone components, signal-based state, inputs and outputs, and the built-in template control flow.
A standalone component
npm install -g @angular/cli
ng new shop --style=scss --routing
cd shop && ng serve # dev server on http://localhost:4200
ng generate component cart/item # creates the four files for one component
ng generate service cart # service skeleton with injectable metadata// cart-item.component.ts
import { Component, input, output, signal, computed } from '@angular/core'
import { CurrencyPipe } from '@angular/common'
@Component({
selector: 'app-cart-item',
imports: [CurrencyPipe], // standalone: only what this component uses
template: `
<li class="item" [class.active]="selected()">
<span>{{ name() }}</span>
<span>{{ price() | currency }}</span>
<button (click)="pick.emit(id())" [disabled]="soldOut()">Add</button>
</li>
`
})
export class CartItemComponent {
id = input.required<string>()
name = input.required<string>()
price = input(0)
selected = input(false)
soldOut = input(false)
pick = output<string>()
readonly label = computed(() => this.name().toUpperCase())
}- Standalone components declare their own dependencies in
importsinstead of being registered in an NgModule; recent versions treat standalone as the default. input()andoutput()are signal-based: read an input by calling it, and emit by callingemit()on the output.signal()holds local state andcomputed()derives from it; reading a signal in a template subscribes the view to it.- Decorator metadata is read at compile time, so keep the class body free of logic that a template should own.
Binding and control flow
<img [src]="avatarUrl()" [alt]="name() + ' avatar'">
<button (click)="add()" [disabled]="busy()">Add to cart</button>
<input [(ngModel)]="query" placeholder="Search"> <!-- needs FormsModule -->
@if (items().length) {
<ul>
@for (item of items(); track item.id) {
<li>{{ item.name }} - {{ item.price | currency }}</li>
} @empty {
<li>No matches</li>
}
</ul>
} @else {
<p>Nothing yet.</p>
}
@switch (status()) {
@case ('draft') { <span>Draft</span> }
@case ('live') { <span>Live</span> }
@default { <span>Unknown</span> }
}| Syntax | Direction | Example |
|---|---|---|
{{ }} | Interpolation | {{ total() }} |
[prop] | Component to DOM | [disabled]="busy()" |
(event) | DOM to component | (click)="save()" |
[(ngModel)] | Two-way | Form controls (template-driven) |
@if / @for / @switch | Control flow | Replaced *ngIf and *ngFor |
💡
The
track expression in @for is required, and it is not ceremony: Angular uses it to move DOM nodes instead of destroying and recreating them when the list changes. Track a stable id, not the loop index.Lifecycle and communication
import { Component, signal, computed, effect, afterNextRender, inject } from '@angular/core'
import { CartStore } from '../cart.store'
@Component({ selector: 'app-cart', template: '...' })
export class CartComponent {
private cart = inject(CartStore)
readonly total = computed(() => this.cart.items().reduce((t, i) => t + i.price, 0))
constructor() {
effect(() => console.log('items changed:', this.cart.items().length))
afterNextRender(() => {
// safe place for DOM measurement or a browser-only library
})
}
}ngOnInitstill works for class-based setup, but signals andeffect()cover most of whatngOnChangesused to do.effect()is for side effects that follow state, not for propagating state to other signals.afterNextRenderruns in the browser only, which keeps server-side rendering safe for DOM access.- Parents pass data down with inputs and listen upwards with outputs; avoid reading a child's internals from the parent.
FAQ
Do I need NgModules?
Not for new applications. Standalone components, directives and pipes are the current model; NgModules remain supported for existing code and third-party libraries that still export them.
signals or RxJS?
Signals for component state and derived values — they are synchronous, glitch-free and easy to read in a template. RxJS for streams of events over time: debounced input, websockets, complex cancellation.
Related
Services and dependency injection Components, props and events
Last refreshed 2026-09-18.