リアクティブフォームを用いたカスタムバリデータの利用
リアクティブフォームでカスタムバリデータを利用する時には、フォームを表す FormGroup オブジェクトと、 それぞれのコントロールを表す FormControl オブジェクトを作成します。 そしてフォームに FormGroup オブジェクトをバインドします。
FormControl オブジェクトにはバリデータ (validators) を取り付けることができ、それぞれのコントロールで必要な検証を行うことが可能になります。
ここでは単純な入力検証を行うバリデータを作成して、バリデータの作成方法を示します。
それでは、ここではユーザー名 (Username) の長さチェックを行うカスタムバリデータを作成します。
実は長さをチェックするだけの検証なら、テンプレート駆動フォームでも input 要素に minlength 属性を設定しておくだけで実現可能です。ここの例はあくまでもバリデータの作成例としてみてください。
src/app/usernameValidator.ts に次のクラスを作成します。
import {FormControl} from '@angular/forms';
export class UsernameValidator {
static isLongEnough(formControl: FormControl){
return { isLongEnough: formControl.value.length > 5 };
}
}
isLongEnough というスタティックメソッドは、値が長さ 5 より大きいときに true の値を持つオブジェクトを返します。
これを使う FormGroup と FromControl は次のように定義します。
src/app/login-form.component.ts として次を作成します。
import {Component} from '@angular/core';
import {FormGroup, FormControl, Validators} from '@angular/forms';
import {UsernameValidator} from './usernameValidator';
@Component({
selector: 'login-form',
templateUrl: './login-form.component.html'
})
export class LoginFormComponent {
form1 = new FormGroup({
username: new FormControl(
'',
Validators.compose([
Validators.required,
UsernameValidator.isLongEnough
])),
password: new FormControl(
'',
Validators.required)
});
onSubmit(){
console.log("Submitted: " + JSON.stringify(this.form1.value));
}
}
テンプレート src/app/login-form.component.html は次の通り。
<form [formGroup]="form1" (ngSubmit)="onSubmit()" class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">Username</label>
<div class="col-sm-5">
<input
formControlName="username"
id="username"
name="username"
type="text"
class="form-control">
<div
*ngIf="form1.controls.username.touched
&& ( !form1.controls.username.errors.isLongEnough
|| form1.controls.username.errors.required )"
class="alert alert-danger">
<span class="glyphicon glyphicon-exclamation-sign"></span>
<span *ngIf="form1.controls.username.errors.required">
Please enter username.
</span>
<span *ngIf="!form1.controls.username.errors.isLongEnough">
Username must be at least 6 character long.
</span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Password</label>
<div class="col-sm-5">
<input
formControlName="password"
name="password"
id="password"
type="password"
class="form-control">
<div
*ngIf="form1.controls.password.touched
&& !form1.controls.password.valid"
class="alert alert-danger">
<span class="glyphicon glyphicon-exclamation-sign"></span>
Please enter password.
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button
type="submit"
[disabled]="( !form1.controls.username.errors.isLongEnough
|| form1.controls.username.errors.required
|| !form1.controls.password.valid )"
class="btn btn-primary">Sign in</button>
</div>
</div>
</form>
ポイントは form 要素で [formGroup]="form1" として、 コンポーネントのコードで作成した FormGroup 型のプロパティ form1 とバインドしているところです。
それぞれのコントロールでは、formControlName 属性で FormControl オブジェクトと接続しています。
これによって、form1.controls.username.errors とか form1.controls.password.errors などの erros オブジェクトとか、form1.controls.password.valid 属性が利用可能となり、それぞれのコントロールの状態に依存したフォームのコントロールが可能になります。
ReactiveFormsModule
リアクティブ・フォームを使うために、ReactiveFormsModule をインポートします。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { LoginFormComponent } from './login-form.component';
@NgModule({
declarations: [
AppComponent,
LoginFormComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
以上でカスタムバリデータ付きのリアクティブ・フォームが作成できました。