双方向バインディングは、アプリケーションのコンポーネントにデータを共有する方法を提供します。 親コンポーネントと子コンポーネントの間でイベントをリスンし、値を同時に更新するには、双方向バインディングを使用します。
双方向バインディングは、プロパティバインディングとイベントバインディングを組み合わせたものです。
バインディング | 詳細 |
---|---|
プロパティバインディング | 特定の要素のプロパティを設定します。 |
イベントバインディング | 要素の変更イベントをリスンします。 |
双方向データバインディングの追加
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 を参照してください。