Signal-based Inputs & Model
Use the modern input(), output(), and model() functions as signal-based alternatives to @Input and @Output.
input()
The input() function creates a signal-based input, readable with the same () call syntax as any other signal — a modern alternative to the @Input() decorator.
import { Component, input } from '@angular/core';
@Component({ selector: 'app-product-card', standalone: true, template: `<h3>{{ title() }}</h3>`,})export class ProductCardComponent { title = input(''); // input signal with a default value}Required and Transformed Inputs
export class ProductCardComponent { title = input.required<string>(); price = input(0, { transform: (value: string | number) => Number(value), // transform incoming values });}output()
The output() function is the signal-era alternative to @Output() + EventEmitter, with a simpler API for emitting events.
import { Component, output } from '@angular/core';
@Component({ selector: 'app-like-button', standalone: true, template: `<button (click)="liked.emit()">👍 Like</button>`,})export class LikeButtonComponent { liked = output<void>();}model() for Two-Way Binding
model() combines an input and its matching output into one declaration, directly enabling the [(...)] banana-in-a-box syntax on your own component with a single line, instead of pairing a separate input() and output().
import { Component, model } from '@angular/core';
@Component({ selector: 'app-stepper', standalone: true, template: ` <button (click)="value.set(value() - 1)">-</button> {{ value() }} <button (click)="value.set(value() + 1)">+</button> `,})export class StepperComponent { value = model(0);}<app-stepper [(value)]="quantity" />Compare this to the earlier @Input()/@Output() two-way binding lesson, which required a separate value input and valueChange output — model() achieves the identical result in a single line.
FAQs
Signal-based input()/output()/model() are the modern recommendation for new code — they integrate directly with computed() and effect() without any extra conversion step.
Technically possible during migration, but pick one style per component for clarity — mixing both in the same class is confusing to read.
Summary
input(), output(), and model() bring signal-based reactivity directly to component communication, with model() notably collapsing two-way binding into a single declaration. Next, you'll look at how change detection itself works, both classically and with signals.