Signal Inputs, Outputs & Model
Angular 21 — Replace @Input/@Output decorators with functional signal APIs
About This Feature
Angular 21 provides functional alternatives to decorator-based component I/O. These are now the preferred approach for new components.
input(defaultValue)— creates a read-only Signal for incoming data. The value is set by the parent via property binding.input.required<T>()— same as above but the TypeScript compiler enforces that the parent must provide a value.output<T>()— replaces@Output() EventEmitter. Call.emit(value)to fire events.model(defaultValue)— creates a WritableSignal that enables two-way binding ([(property)]). The child can read and write; writes automatically propagate back to the parent's signal.
Code Example
// child component
import { input, output, model } from '@angular/core';
export class SignalCardComponent {
// Required input signal — compiler enforces parent provides it
name = input.required<string>();
// Optional input signal with default value
color = input('#667eea');
// model() — two-way bindable; child writes propagate to parent signal
liked = model(false);
// output() replaces @Output() EventEmitter
greet = output<string>();
onGreet() {
this.greet.emit(`Hello from ${this.name()}!`);
}
}
// parent template
<app-signal-card
[name]="cardName()"
[color]="cardColor()"
[(liked)]="isLiked"
(greet)="onGreet($event)" />
// Reading signals in the child template
{{ name() }} // read input signal
{{ liked() }} // read model signal
liked.update(v => !v) // write model signal → updates parent tooLive Demo
Control the child component from the parent using signals:
(model() in sync — child can also toggle it)
Hello, Angular Developer!
This card uses input(), output(), and model()
model() value: false (parent & child stay in sync)
Parent signal reads: cardName() = "Angular Developer" | isLiked() = false