テンプレート駆動フォームの作成
ここではテンプレート駆動フォーム (template driven forms) を作成する具体的な方法を示します。
データバインディング や テンプレート参照変数 の知識が必要です。
テンプレート駆動フォームの作成手順は次の通りです。
- フォームで作成・編集するデータのモデルクラスを作成する。
- フォームを制御するためのコンポーネントを作成する。
- ルートモジュールにて FormsModule とフォームコンポーネントを取り込む。
- テンプレートでフォームを作成する。
- コントロールには name 属性を設定
- form にはサブミット時のハンドラを設定 (ngSubmit)="onSubmit()"
- form にはテンプレート参照変数を設定 #form1="ngForm"
- モデルクラスのプロパティとフォームコントロールを 2 方向データバインディングでバインドする。
- [(ngModel)]="employee.email"
- テンプレート参照変数を ngModel に設定する。
- #email="ngModel"
- CSS クラス・バインディングとスタイルバインディングを用いて入力状態 (エラーメッセージ等) に関する UI を制御
コントロールの状態
コントロールのテンプレート参照変数に ngModel を設定することで、コントロールの状態と変数の以下のプロパティが連動します。
True | False | |
---|---|---|
値は適切か | valid | invalid |
入力ボックスを触ったか | touched | untouched |
変更があったか | dirty | pristine |
具体例でみてみよう
ここでは実際にフォームを作成してみましょう。出来上がりは次のようなフォームです。
Name と Email は必須入力項目、Nickname は任意としましょう。
尚、ここでは Bootstrap を使いますので、Angular プロジェクトを作成したら Bootstrap を設定してください。
モデルクラスの作成
ここでは従業員 (employee) を登録するフォームを作成するので、モデルクラスとして次の Employee クラスを作成します。
src/app/employee.ts として次を作成します。
export class Employee {
constructor(
public name: string,
public email: string,
public nickname?: string){}
}
フォームコンポーネント作成
次にフォームを制御するフォームコンポーネントを作ります。
src/app/form1.component.ts は次の通り。
import {Component} from '@angular/core';
import {NgForm} from '@angular/forms';
import {Employee} from './employee';
@Component({
selector: 'form1',
templateUrl: './form1.component.html'
})
export class Form1Component {
employee = new Employee('', '', '');
onSubmit(){
console.log('Submitted:' + JSON.stringify(this.employee));
}
}
テンプレートは次の通り。
<form
class="form-horizontal"
(ngSubmit)="onSubmit()"
#form1="ngForm">
<div class="form-group">
<label class="col-sm-2 control-label">Name</label>
<div class="col-sm-5">
<input
type="text"
name="name"
required
class="form-control"
[(ngModel)]="employee.name"
#name="ngModel">
<div
class="alert alert-danger"
[hidden]="name.valid || name.untouched">
<span class="glyphicon glyphicon-exclamation-sign"></span> Name is required
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Nickname</label>
<div class="col-sm-5">
<input
type="text"
class="form-control"
name="nickname"
[(ngModel)]="employee.nickname"
#nickname>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Email</label>
<div class="col-sm-5">
<input
type="text"
class="form-control"
name="email"
required
[(ngModel)]="employee.email"
#email="ngModel">
<div
class="alert alert-danger"
[hidden]="email.valid || email.untouched">
<span class="glyphicon glyphicon-exclamation-sign"></span> Email is required</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-5">
<button
type="submit"
class="btn btn-primary"
[disabled]="!form1.form.valid">Submit</button>
</div>
</div>
</form>
ルートモジュールの編集
src/app/app.module.ts に上で作成した Form1Component を取り込みます。もし、FormsModule がインポートされていなければインポートします。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { Form1Component } from './form1.component';
@NgModule({
declarations: [
AppComponent,
Form1Component
],
imports: [
BrowserModule,
FormsModule,
HttpModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
以上でコントロールに関連付けされたテンプレート参照変数のプロパティを用いて、 フォームを制御できるはずです。
入力検証は?
上記では入力検証 (valid か invalid か) という点では、HTML 要素に記述する required 属性に依存しています。
しかし HTML での入力チェックはかなりサポート範囲が広がっており、 minlength などで最低限の文字数チェックなどの簡単なことだけではなく、 pattern 属性で正規表現による入力チェック等も可能になっています。
モデル駆動フォームでカスタムバリデータを実装する前に、HTML5 で可能なことを探るのが賢明です。