@Input
| Since: | Angular 16(2023) |
|---|
The @Input decorator in Angular marks a class property as an input that can receive data from a parent component via property binding. When the parent updates the bound value, Angular passes the new value down to the child component. This is the primary mechanism for parent-to-child communication in Angular.
Syntax
import { Component, Input } from '@angular/core';
@Component({ selector: 'app-child', template: `{{ title }}`, standalone: true })
export class ChildComponent {
@Input() title = ''; // basic
@Input('labelText') label = ''; // alias: parent uses [labelText]
}
<!-- Parent template --> <app-child [title]="parentTitle" [labelText]="parentLabel" />
@Input Options
| Option | Overview |
|---|---|
alias | Specifies the name used in the parent template. The component class uses its own property name internally. |
required | (Angular 16+) Marks the input as required. The compiler reports an error if the parent does not bind it. |
transform | (Angular 16+) A function that transforms the raw bound value before it is assigned. Built-in helpers include numberAttribute and booleanAttribute. |
Sample Code
A product card component that receives product data via @Input.
// product-card.component.ts
import { Component, Input } from '@angular/core';
interface Product {
id: number;
name: string;
price: number;
}
@Component({
selector: 'app-product-card',
template: `
<div>
<h3>{{ product.name }}</h3>
<p>{{ product.price | currency:'JPY':'symbol':'1.0-0' }}</p>
</div>
`,
standalone: true,
})
export class ProductCardComponent {
@Input() product!: Product;
}
// app.component.ts
import { Component } from '@angular/core';
import { ProductCardComponent } from './product-card.component';
@Component({
selector: 'app-root',
template: `
<app-product-card [product]="item" />
`,
imports: [ProductCardComponent],
standalone: true,
})
export class AppComponent {
item = { id: 1, name: 'Lab Widget', price: 9800 };
}
Using an alias so the parent binds with a different name.
// label.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-label',
template: `<span>{{ displayText }}</span>`,
standalone: true,
})
export class LabelComponent {
// Parent uses [labelText]; the class property is displayText
@Input('labelText') displayText = '';
}
<app-label [labelText]="'Future Gadget Lab'" />
Marking an input as required (Angular 16+).
// member-badge.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-member-badge',
template: `<span>#{{ memberId }} — {{ memberName }}</span>`,
standalone: true,
})
export class MemberBadgeComponent {
@Input({ required: true }) memberId!: number;
@Input({ required: true }) memberName!: string;
}
<!-- Parent must provide both inputs --> <app-member-badge [memberId]="1" [memberName]="'Okabe Rintaro'" />
Using transform with numberAttribute and booleanAttribute to coerce string attribute values to the correct types.
// member-card.component.ts
import { Component, Input } from '@angular/core';
import { numberAttribute, booleanAttribute } from '@angular/core';
@Component({
selector: 'app-member-card',
template: `
<p>{{ name }} (Level {{ level }}) {{ isSenior ? '★' : '' }}</p>
`,
standalone: true,
})
export class MemberCardComponent {
@Input() name = '';
@Input({ transform: numberAttribute }) level = 1;
@Input({ transform: booleanAttribute }) isSenior = false;
}
<!-- Attribute bindings pass strings; transform converts them --> <app-member-card name="Makise Kurisu" level="4" isSenior />
Summary
@Input is the standard way to pass data from a parent component to a child component. The parent binds a value using [propertyName]="value", and the child declares the receiving property with @Input(). When the parent's value changes, Angular automatically updates the child's property.
Angular 16+ added required (compile-time enforcement) and transform (automatic coercion) to @Input, reducing boilerplate for common patterns. For reacting to input changes in the component class, see ngOnChanges. For child-to-parent communication, see @Output and EventEmitter.
Common Mistake: Binding an attribute instead of a property
Without the square brackets, Angular treats the value as a string literal, not as a bound expression. If the input expects a number or object, the string will be passed instead.
<!-- NG: passes the string "item" instead of the component property --> <app-product-card product="item" />
<!-- OK: property binding evaluates the expression --> <app-product-card [product]="item" />
Common Mistake: Forgetting to bind a required input
With @Input({ required: true }), the Angular compiler enforces that the parent binds the input. Forgetting it causes a compile-time error, catching the mistake early.
// NG: required input memberId not bound — compile error <app-member-badge [memberName]="'Okabe Rintaro'" />
// OK: all required inputs are bound <app-member-badge [memberId]="1" [memberName]="'Okabe Rintaro'" />
If you find any errors or copyright issues, please contact us.