この記事の目的
この記事は、
Angular のいろいろなバインド方法と種類を自分なりにまとめること
を目的としています。
本題
データバインディングの種類がいろいろあってわからない。
コンポーネント→Viewへのバインディング {{ }} 型
//template {{interpolationValue}} //Component public interpolationValue: string = "Public"; private interpolationValuePrivate: string = "Private";
- Componentのクラス変数として定義したものをバインドできる。
- アクセス修飾子は、PrivateでもPublicでもバインドできた。
- 注意事項↓
Angular では、 目 に 見える 以上 に{{...}} 式 を 何度 も 評価 し ます。 時間 の かかる 式 は、 そのまま アプリ の 速度 低下 に つながる 可能性 が ある ので、 注意 し て ください。
山田 祥寛. Angularアプリケーションプログラミング (Kindle の位置No.1191-1192).
コンポーネント→Viewへのバインディング プロパティバインド型
< img [src]=" parameter" /> < img bind-src="parameter" /> < img [src]=" {{parameter}}" />
- コンポーネントのプロパティに値をバインドする際は、プロパティバインド型のバインドを行う。
- 構文は3種類あるが、どれを使っても同じ。
その他のバインディング方法は?
子コンポーネントへのデータバインディングってどうやるの?
子コンポーネントとの双方向バインディング
- @Input/outputを駆使して、同期処理を実装する。
- [(ngModel)]みたいな動きになる実装もできる
参照元記事でもやられていますが、実際にやってみました。
やってみた結果、以下のコードで、親子間でのデータバインドを双方で実現することができました。これは便利。ただ、この実装では、子のInputに対しては、値の入力が確定して、かつ、値が変更されたタイミングでのみ親に変更が伝わりますが、親から子へは、値の変更がリアルタイムで伝わるので、値の伝わる向きによってタイムラグが出てしまいます。これは、子コンポーネントのEmitタイミングの調整が必要です。
//親コンポーネント用html <sample-component [(item)]="Paramter"></sample-component> <mat-form-field> <- 以下は確認用のInput要素 <mat-label>Parent Input</mat-label> <input matInput [(ngModel)]="Paramter" (change)="change($event.target.value)"> </mat-form-field>
//親コンポーネントの実装は特になし
//子コンポーネント用html <mat-form-field> <mat-label>Child Input</mat-label> <input matInput [(ngModel)]="item" ←@Inputを双方向バインドする。 (change)="change($event.target.value)"> </mat-form-field>
//子コンポーネント @Input() item: string; @Output() itemChange = new EventEmitter<string>(); change(value: any) { this.item = value; this.itemChange.emit(this.item); }
番外編)バインディングするときに詰まったこと
以下のような実装をした時、バインドが実行されず、詰まりました。
<form class="example-form"> <mat-form-field class="example-full-width"> <mat-label>Sample Input</mat-label> <input matInput placeholder="Ex. Pizza" [(ngModel)]="Paramter"> </mat-form-field> </form>
エラー内容は以下の通りです。
ERROR
Error: If ngModel is used within a form tag, either the name attribute must be set or the form
control must be defined as 'standalone' in ngModelOptions.
Example 1: <input [(ngModel)]="person.firstName" name="first">
Example 2: <input [(ngModel)]="person.firstName" [ngModelOptions]="{standalone: true}">
Angularのエラーメッセージは、どう直せばいいか丁寧に教えてくれるので、助かります。理由をちゃんと理解していませんが、このような場合(Formタグ内でngModelのバインディングを利用する場合)、name属性の指定が必須となるようです。このことから、Formタグを外して利用するか、上記2例を参考に実装することで、ngModelを利用した双方向バインディングが利用できるようになることがわかります。FormGroupを利用しないのであれば、Formタグでくくる必要もないはずなので、Formタグを外しても害はない。はず。修正後の実装は以下の通りです。
//FORMタグを外す <mat-form-field class="example-full-width"> <mat-label>Sample Input</mat-label> <input matInput name="SampleInput" placeholder="Ex. Pizza" [(ngModel)]="Paramter"> </mat-form-field> //Name属性を付ける。 <form class="example-form"> <mat-form-field class="example-full-width"> <mat-label>Sample Input</mat-label> <input matInput name="SampleInput" placeholder="Ex. Pizza" [(ngModel)]="Paramter"> </mat-form-field> </form>
以上です。