双方向バインディングは、アプリケーションのコンポーネントにデータを共有する方法を提供します。 親コンポーネントと子コンポーネントの間でイベントをリスンし、値を同時に更新するには、双方向バインディングを使用します。
双方向バインディングは、プロパティバインディングとイベントバインディングを組み合わせたものです。
| バインディング | 詳細 |
|---|---|
| プロパティバインディング | 特定の要素のプロパティを設定します。 |
| イベントバインディング | 要素の変更イベントをリスンします。 |
双方向データバインディングの追加
Angularの双方向バインディング構文は、角括弧と丸括弧を組み合わせた [()] です。
[()] 構文は、プロパティバインディングの角括弧 [] とイベントバインディングの丸括弧 () を以下のように組み合わせます。
src/app/app.component.html
<h1 id="two-way">Two-way Binding</h1><div id="two-way-1"> <app-sizer [(size)]="fontSizePx"></app-sizer> <div [style.font-size.px]="fontSizePx">Resizable Text</div> <label for="font-size">FontSize (px): <input id="font-size" [(ngModel)]="fontSizePx"></label></div><br><div id="two-way-2"> <h2>De-sugared two-way binding</h2> <app-sizer [size]="fontSizePx" (sizeChange)="fontSizePx=$event"></app-sizer></div>
双方向バインディングの仕組み
双方向バインディングが機能するためには、@Output() プロパティは inputChange というパターンを使用する必要があります。ここで、input は @Input() プロパティの名前です。
たとえば、@Input() プロパティが size の場合、@Output() プロパティは sizeChange でなければなりません。
次の sizerComponent には、size 値プロパティと sizeChange イベントがあります。
size プロパティは @Input() なので、データは sizerComponent に流入できます。
sizeChange イベントは @Output() で、データが sizerComponent から親コンポーネントに流出することを可能にします。
次に、フォントサイズを小さくする dec() メソッドと、フォントサイズを大きくする inc() メソッドの2つのメソッドがあります。
これらの2つのメソッドは、resize() を使用して size プロパティの値を最小値/最大値の制約内で変更し、新しい size 値を伝えるイベントを発行します。
src/app/sizer.component.ts
import {Component, Input, Output, EventEmitter} from '@angular/core';@Component({ standalone: true, selector: 'app-sizer', templateUrl: './sizer.component.html', styleUrls: ['./sizer.component.css'],})export class SizerComponent { @Input() size!: number | string; @Output() sizeChange = new EventEmitter<number>(); dec() { this.resize(-1); } inc() { this.resize(+1); } resize(delta: number) { this.size = Math.min(40, Math.max(8, +this.size + delta)); this.sizeChange.emit(this.size); }}
sizerComponent テンプレートには、それぞれクリックイベントを inc() メソッドと dec() メソッドにバインドする2つのボタンがあります。
ユーザーがボタンのいずれかをクリックすると、sizerComponent は対応するメソッドを呼び出します。
inc() メソッドと dec() メソッドの両方が、+1 または -1 で resize() メソッドを呼び出し、それは新しいサイズ値で sizeChange イベントを発生させます。
src/app/sizer.component.html
<div> <button type="button" (click)="dec()" title="smaller">-</button> <button type="button" (click)="inc()" title="bigger">+</button> <span [style.font-size.px]="size">FontSize: {{size}}px</span></div>
AppComponent テンプレートでは、fontSizePx は SizerComponent に双方向にバインドされます。
src/app/app.component.html
<h1 id="two-way">Two-way Binding</h1><div id="two-way-1"> <app-sizer [(size)]="fontSizePx"></app-sizer> <div [style.font-size.px]="fontSizePx">Resizable Text</div> <label for="font-size">FontSize (px): <input id="font-size" [(ngModel)]="fontSizePx"></label></div><br><div id="two-way-2"> <h2>De-sugared two-way binding</h2> <app-sizer [size]="fontSizePx" (sizeChange)="fontSizePx=$event"></app-sizer></div>
AppComponent では、fontSizePx は SizerComponent.size の初期値を 16 に設定することで確立します。
src/app/app.component.ts
import {Component} from '@angular/core';import {SizerComponent} from './sizer/sizer.component';import {FormsModule} from '@angular/forms';@Component({ standalone: true, selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], imports: [FormsModule, SizerComponent],})export class AppComponent { fontSizePx = 16;}
ボタンをクリックすると、AppComponent.fontSizePx が更新されます。
修正された AppComponent.fontSizePx 値はスタイルバインディングを更新し、表示されているテキストが大きくなったり小さくなったりします。
双方向バインディング構文は、プロパティバインディングとイベントバインディングの組み合わせの省略形です。
SizerComponent のバインディングを別々のプロパティバインディングとイベントバインディングとして示すと、次のようになります。
src/app/app.component.html (expanded)
<h1 id="two-way">Two-way Binding</h1><div id="two-way-1"> <app-sizer [(size)]="fontSizePx"></app-sizer> <div [style.font-size.px]="fontSizePx">Resizable Text</div> <label for="font-size">FontSize (px): <input id="font-size" [(ngModel)]="fontSizePx"></label></div><br><div id="two-way-2"> <h2>De-sugared two-way binding</h2> <app-sizer [size]="fontSizePx" (sizeChange)="fontSizePx=$event"></app-sizer></div>
$event 変数には SizerComponent.sizeChange イベントのデータが含まれます。
ユーザーがボタンをクリックすると、Angularは $event 値を AppComponent.fontSizePx に割り当てます。
フォームでの双方向バインディング
組み込みのHTML要素は x 値と xChange イベントのパターンに従わないため、フォーム要素での双方向バインディングには NgModel が必要です。
フォームでの双方向バインディングの使用方法の詳細については、Angularの NgModel を参照してください。