フォームとバリデーター
Angular 2では、フォームの機能を拡張するディレクティブにより、入力検証用のバリデーターなど便利な機能が利用できます。
Angular 2の流儀でフォームを記述
Angular 2のフォームとバリデーターを利用する例をリスト11に示します。
<!-- ngForm形式でフォームを記述 ...(1)--> <form #myForm="ngForm" (ngSubmit)="onSubmitForm(myForm)" novalidate> <h4>名前</h4> <!-- 必須バリデーター ...(2)--> <input type="text" name="familyName" [(ngModel)]="formData.familyName" required> <input type="text" name="givenName" [(ngModel)]="formData.givenName" required> <h4>年齢</h4> <!-- パターンバリデーター ...(3)--> <input type="text" name="age" [(ngModel)]="formData.age" pattern="1?[0-9]{0,2}">歳 <h4>趣味</h4> <!-- 最短長バリデーター ...(4)--> <input type="text" name="hobby" [(ngModel)]="formData.hobby" minlength="4"> <div style="margin-top:20px"> <button type="submit">フォーム送信</button> </div> </form>
(1)がフォームの定義です。「#myForm="ngForm"」記述は、このフォームをAngular 2のフォームとしてmyFormという名前で定義することを表します。また(ngSubmit)属性はフォームがサブミットされた時のイベントです。novalidateはAngular 2ではなくHTML5の属性で、HTML5のバリデーター機能を無効にしてAngular 2のバリデーターと干渉しないように設定しています。
(2)は必須バリデーターを指定する例です。required属性で必須バリデーターが有効になります。(3)はバリデーターに入力パターンを指定する例です。pattern属性に正規表現でパターンを指定します。(4)はバリデータとして文字列の最短の長さを指定する例です。minlength属性に最短の長さ4を指定しています。なお最長の長さをmaxlength属性で指定することもできます。
(2)〜(4)には[(ngModel)]属性により双方向データバインディングが設定されています。対応する変数formDataはコンポーネントにリスト12のように記述します。
formData = { familyName: "山田", givenName: "太郎", age: 40, hobby: "映画鑑賞" };
フォーム要素に自動適用されるCSSクラス
Angular 2のフォームを利用すると、テキストボックスなどのフォーム要素に表1のCSSクラスが自動的に適用されます。これらのクラスにスタイルを定義することで入力エラーなどを表示できます。
要素の状態 | クラス |
---|---|
コンポーネントを一度も操作していない | ng-untouched |
コンポーネントを1回以上操作した | ng-touched |
値が変更されていない | ng-pristine |
値が変更された | ng-dirty |
バリデーターが正しい値と判断 | ng-valid |
バリデーターが誤った値と判断 | ng-invalid |
リスト11、12を含むサンプルコード(angular2-004-form)では表1のCSSクラスを設定して、以下のように表示されるようになっています。
- テキストボックスを1回選択すると灰色の背景になる
- テキストボックスの値を変更すると文字が斜体になる
- テキストボックスに誤った値を入力すると赤枠が表示される
サブミットボタン押下時の処理onSubmitFormはリスト13です。Angular 2のフォームオブジェクトformから、validプロパティでフォーム全体の検証結果を取得して、処理を切り替えています。
onSubmitForm(form) { // フォームが誤った値の場合はエラー表示してサブミット中止 if (!form.valid) { alert("Validatorエラー発生"); return false; } // フォームが正しい値の場合はサブミット form.submit(); }
なお、リスト11〜13と同じ動作をするAngularJS 1の実装例は、ダウンロードできるサンプルコード(angularjs1-samples/004-form.html)に含まれています。
参考 Angular 2のディレクティブを定義する記号
本記事で説明したAngular 2のディレクティブで使用されていた記号とその意味を表2に示します。
No. | 記号 | 意味 |
---|---|---|
1 | [( )] | 双方向データバインディング |
2 | ( ) | イベントハンドラ |
3 | [ ] | 属性値の設定 |
4 | * | テンプレート |
5 | # | 変数の定義 |
No.1はリスト2の[(ngModel)]、No.2はリスト5の(click)で説明しました。No.3はリスト9の[ngStyle]でCSSを指定するときに利用しています。No.4はリスト9の*ngFor、*ngIfで利用しており、ngFor、ngIf属性が指定された要素を内部的にテンプレートとして取り扱い、繰り返しで複数回表示したり、条件分岐で表示/非表示を切り替えたりしています。No.5の変数定義はリスト11の「#myForm="ngForm"」記述で、フォームを変数myFormで参照するために用いています。
AngularJS 1では、ng-modelは双方向データバインディング、ng-clickがクリックのイベントハンドラといったように、ディレクティブ名だけで意味を定義していましたが、Angular 2ではディレクティブ名に付加される記号で意味が統一的に把握できるようになりました。
まとめ
本記事では、AngularJSの特徴的な機能であるデータバインディングやディレクティブを「Angular 2」で利用する方法を説明しました。今回紹介した範囲でAngular 2とAngularJS 1の記述を比較すると表3のようになります。
種類 | Angular 2 | AngularJS 1 |
---|---|---|
片方向データバインディング | {{ }} | {{ }} |
双方向データバインディング | [(ngModel)] | ng-model |
イベント | (イベント名) | ng-イベント名 |
繰り返しディレクティブ | *ngFor | ng-repeat |
条件分岐ディレクティブ | *ngIf | ng-if |
スタイル指定 | [ngStyle] | ng-style |
片方向データバインディングは同一記述ですが、それ以外は記述形式が異なります。名前が似ていて類推できるものが多いですが、*ngForとng-repeatのように名前から異なっているものもあります。とはいえ基本的な処理の考え方はAngularJS 1がベースになっているため、Angular 2のAPIリファレンスを参照してAngularJS 1との対応関係を把握すれば、比較的早く習熟できるでしょう。