← 解説「input() — 親から値を受け取る」に戻る
サンプルコードで身につける: input() — 親から値を受け取る
解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。
1親から文字列を1つ受け取る
input.required の最小例で、親が [userName] で渡した文字列を子が表示します。受け取った値はシグナルなので userName() と関数として読む、という点が最初のつまずきポイントです。「親がデータを持ち、子は受け取って表示する」関係の出発点になります。
import { Component, input } from '@angular/core';
@Component({
selector: 'app-user-name',
// 受け取った値はシグナルなので userName() と読む
template: '<p>{{ userName() }}さん</p>',
})
export class UserNameComponent {
// 親から必ず渡してもらう入力
userName = input.required<string>();
}
// 親側: <app-user-name [userName]="loginUser" />
2デフォルト値付きの省略可能な入力
input('概要') のように初期値を渡すと、親が値を渡さなかったときにその値が使われます。「必須の入力は required、任意の入力はデフォルト値」という使い分けの基本形です。見出しコンポーネントのように、細かい調整は任意で受け付ける部品でよく使います。
import { Component, input } from '@angular/core';
@Component({
selector: 'app-page-title',
template: '<h1>{{ titleText() }}</h1><p>{{ subtitle() }}</p>',
})
export class PageTitleComponent {
titleText = input.required<string>();
subtitle = input('概要'); // 渡されなければ '概要' になる
}
// 親側: <app-page-title [titleText]="pageName" />
// subtitle を渡さなければ「概要」と表示される
3オブジェクトを型付きで受け取る
input は文字列だけでなく、型引数を指定すればオブジェクトでも数値でも受け取れます。商品オブジェクトを丸ごと受け取る形は、関連する値をバラバラに渡すより宣言が少なく済み、型チェックも効きます。一覧の1行・1カードを表す子コンポーネントの定番スタイルです。
import { Component, input } from '@angular/core';
type Product = { id: number; productName: string; price: number };
@Component({
selector: 'app-price-tag',
// オブジェクトのプロパティには product().price のようにアクセスする
template: '<p>{{ product().productName }}: {{ product().price }} 円</p>',
})
export class PriceTagComponent {
product = input.required<Product>();
}
// 親側: <app-price-tag [product]="selectedProduct" />
4受け取った値で表示を出し分ける
input で受け取った在庫数をそのまま @if の条件に使い、子の中で表示を出し分ける例です。親は数値を渡すだけでよく、「どう見せるか」の判断は子に閉じ込められています。バッジやステータス表示など、判断ロジック付きの小さな表示部品はこの形で作ります。
import { Component, input } from '@angular/core';
@Component({
selector: 'app-stock-badge',
// 受け取ったシグナルはテンプレートの条件式にそのまま使える
template:
'@if (stock() === 0) { <span>在庫切れ</span> }' +
' @else if (stock() <= 3) { <span>残りわずか</span> }' +
' @else { <span>在庫あり</span> }',
})
export class StockBadgeComponent {
stock = input.required<number>();
}
// 親側: <app-stock-badge [stock]="item.stock" />
5一覧の親から各カードへデータを配る
親が記事の配列を持ち、@for で繰り返しながら各記事を子カードへ input で渡す、実務の一覧画面そのままの構成です。「一覧の管理は親、1件の見せ方は子」という分業によって、それぞれのコンポーネントが小さく保たれます。input が親子分業の配線役であることがよく分かる例です。
import { Component, input } from '@angular/core';
type Article = { id: number; articleTitle: string };
@Component({
selector: 'app-article-card',
template: '<article><h2>{{ article().articleTitle }}</h2></article>',
})
export class ArticleCardComponent {
article = input.required<Article>();
}
@Component({
selector: 'app-article-list',
imports: [ArticleCardComponent],
// 繰り返しの中で、1件ずつ子へ渡す
template:
'@for (a of articles; track a.id) { <app-article-card [article]="a" /> }',
})
export class ArticleListComponent {
articles: Article[] = [
{ id: 1, articleTitle: 'シグナル入門' },
{ id: 2, articleTitle: 'DIの基礎' },
];
}