Angular TIPS

Angular TIPS

フォームの入力値をコンポーネントと同期するには?(双方向バインディング)

2017年7月14日

テンプレート上のフォーム入力値とコンポーネントのプロパティ値を双方向にバインドするTwo-way Bindingのバインディング構文を説明し、その仕組みを紹介する。

  • このエントリーをはてなブックマークに追加

【対応バージョン】 Angular 4以降。v4時点で執筆しました。

 {{...}}Property BindingAttribute BindingEvent Bindingなど、ここまでに解説してきたバインド構文は、いずれもコンポーネント→テンプレート方向、もしくはテンプレート→コンポーネント方向の、いわゆる片方向バインディングを表すものでした。

 一方、コンポーネントの値とテンプレート上の値とを双方向に同期させるためのバインド構文を双方向バインディングと言います。コンポーネントの値(プロパティ)が変化したらテンプレートにも反映し、テンプレートの値を変えたら(例えばテキストボックスに値が入力されたら)コンポーネントのプロパティにも書き戻す、そんなバインド構文です。

 具体的な例も見てみましょう。以下は、テキストボックスに入力した値に基づいて、「Hello, ●○!!」というメッセージを表示する例です。テキストボックスにはデフォルト値として「Tom」をセットするものとします。

テキストボックスの値に応じて、挨拶メッセージを表示

テキストボックスに「山田太郎」と入力し直すと……

テキストボックスの値に応じて、挨拶メッセージを表示
テキストボックスの値に応じて、挨拶メッセージを表示

1FormsModuleモジュールをインポートする

 Angularのフォーム機能を利用するために、FormsModuleをインポートしておきます*1。別モジュールをインポートするには、@NgModuleデコレーターのimportsパラメーターを利用します。

TypeScript
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms';

import { AppComponent }  from './app.component';

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }
FormsModuleモジュールをインポートするコード(app.module.ts)
  • *1 Angularのフォーム機能については、後日別稿「TIPS:入力検証機能付きのフォームを実装するには?」で解説する予定です。

2コンポーネントを準備する

 あとは、テキストボックスを備えたコンポーネントを作成するだけです。

TypeScript
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <form>
      <label for="name">名前:</label>
      <!--1テキストボックスtxtNameに対してnameプロパティをひも付け-->
      <input id="txtName" name="txtName" type="text"
        [(ngModel)]="name" />
      <!--2nameプロパティをもとに挨拶メッセージを生成-->
      <div>Hello, {{name}}!!</div>
    </form>
  `,
})
export class AppComponent  {
  // 3デフォルト値を設定
  name = 'Tom';
}
双方向バインディングの基本的な例(app.component.ts)

各番号に対する説明は後の本文に記載しています。

 <input><select>などの入力要素を、コンポーネントのプロパティと同期させるには、ngModelディレクティブを利用します。ngModelを利用する際は、入力要素をコンポーネント側から識別できるように、name属性は必須です。

[構文]ngModelディレクティブ(双方向バインディング)

[(ngModel)]="prop"
  • prop: コンポーネントのプロパティ

 双方向バインディングでは、ngModelディレクティブを[(...)]でくくります。[...]はProperty Binding(コンポーネント→テンプレート)を、(...)はEvent Binding(テンプレート→コンポーネント)を表しますので、両者を組み合わせたのが[(...)](双方向バインディング)というわけです。

 1のように表すことで、テキストボックスtxtNameがコンポーネントのnameプロパティに同期します。つまり、nameプロパティ(3)の初期値がそのままテキストボックスの初期値として反映されますし、テキストボックスを更新すると、プロパティ値にも反映され、結果として2のメッセージにも反映されます。

補足:双方向バインディングの仕組み

 双方向バインディングの仕組みを理解するために、1のコードを双方向バインディングを利用せずに表してみましょう。

HTML
<input id="txtName" name="txtName" type="text"
  [ngModel]="name"
  (input)="name=$event.target.value" />
[(...)]構文を利用せずに双方向バインディングを実装したコード(app.component.ts)

 まず、[ngModel]="name"nameプロパティの値をngModelディレクティブにバインドします。Property Binding構文です。

 「(input)="name=$event.target.value"」はEvent Bindingの構文で、inputイベント(=入力値が変更された)のタイミングで、ターゲット要素($event.target*2)の値(value)をnameプロパティに代入します。

 このように、双方向バインディング([(...)])とは、内部的には、Property BindingとEvent Bindingの組み合わせによって表現できます。

  • *2 $eventはイベント情報を管理するためのイベントオブジェクトです。詳しくは、後日別稿「TIPS:イベント情報を取得するには?」で解説する予定です。
処理対象:テンプレート構文(Template Syntax) カテゴリ:基本
処理対象:双方向バインディング(Two-way Binding) カテゴリ:テンプレート構文(Template Syntax)
処理対象:バインディング構文(Binding Syntax) カテゴリ:テンプレート構文(Template Syntax)
処理対象:[(ngModel)]="プロパティ名" カテゴリ:テンプレート構文(Template Syntax) > バインディング構文(Binding Syntax)
API:NgModel カテゴリ:@angular > forms > DIRECTIVE(ディレクティブ)
API:FormsModule カテゴリ:@angular > forms > CLASS(クラス)
API:@NgModuleデコレーター カテゴリ:ADVANCED > Angular Modules

※以下では、本稿の前後を合わせて5回分(第16回~第20回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

16. Angular CLIで、Angularアプリのコードを自動生成するには?

Angular CLIのng generateコマンドを使ってAngularアプリ用コードを自動生成してみる。また、各アプリのAngular CLI設定ファイルをエディターで編集する方法も紹介する。

17. イベントハンドラーを登録するには?(Event Binding)

要素にイベントハンドラーをバインドするEvent Bindingについて、2つのバインディング構文を説明する。

18. 【現在、表示中】≫ フォームの入力値をコンポーネントと同期するには?(双方向バインディング)

テンプレート上のフォーム入力値とコンポーネントのプロパティ値を双方向にバインドするTwo-way Bindingのバインディング構文を説明し、その仕組みを紹介する。

19. イベントハンドラーでイベント情報を参照するには?($event)

要素にイベントハンドラーをバインドするEvent Bindingで、その引数で得られるイベントオブジェクト「$event」から、イベントに関する詳細情報を取得する方法を説明する。

20. フォームへの入力値をイベントハンドラーで受け取るには?(テンプレート参照変数)

フォーム要素への入力値をイベントとして受け取る方法として、テンプレート参照変数を利用する方法を説明する。

サイトからのお知らせ

Twitterでつぶやこう!