🔖
Angular のクロスフィールドバリデーション
クロスフィールドバリデータ
Angular でフォーム項目同士のバリデーションを実施するケースのバリデーション関数を、クロスフィールドバリデータといいます。
Web アプリケーションでは例えば以下のような場面で利用されるケースが多いでしょう。
- パスワードの入力確認
- 年月日フィールドのチェック
- 姓名フィールドとカナフィールドの読み方一致チェック
フォーム全体へのバリデーション
フォーム全体へのバリデーションとして定義する場合は以下のような形で実装可能です。
import {
AbstractControl,
FormControl,
FormGroup,
ValidationErrors,
ValidatorFn,
Validators,
} from '@angular/forms';
const passwordMatchValidator_form: ValidatorFn = (
control: AbstractControl
): ValidationErrors | null => {
const pass1 = control.get('password');
const pass2 = control.get('password2');
if (pass1.value === pass2.value) {
return null;
} else {
return { passwordMatch: true };
}
};
export const makeAppForm = () => {
return new FormGroup(
{
email: new FormControl('', [Validators.required, Validators.email]),
password: new FormControl('', [Validators.required]),
password2: new FormControl('', [Validators.required]),
},
{ validators: [passwordMatchValidator_form] }
);
};
FormGroup
は第二引数でフォーム全体のバリデーション関数を受け取ることができます。
validator 関数の引数 control
には、FormGroup 全体が渡されるため、get を利用してそれぞれの項目を取得できます。
エラー結果の取得はフォーム全体から form.errors
のようにして取得する必要があり、
password2.errors
のように項目からエラーの状態を検知する事ができません。
フォーム項目のバリデーターとして
フォーム項目のバリデータ関数で、クロスフィールドバリデーションを実現することもできます。
import {
AbstractControl,
FormControl,
FormGroup,
ValidationErrors,
ValidatorFn,
Validators,
} from '@angular/forms';
const passwordMatchValidator_input: ValidatorFn = (
control: AbstractControl
): ValidationErrors | null => {
if (!control.parent) {
return { passwordMatch: true };
}
const pass1 = control.parent.get('password');
const pass2 = control;
if (pass1.value === pass2.value) {
return null;
} else {
return { passwordMatch: true };
}
};
export const makeAppForm = () => {
return new FormGroup(
{
email: new FormControl('', [Validators.required, Validators.email]),
password: new FormControl('', [Validators.required]),
password2: new FormControl('', [
Validators.required,
passwordMatchValidator_input,
]),
}
);
};
この場合カスタムヴァリデータ関数は、 password2 の項目に直接渡すことができます。
注意しなければ行けないのは、 バリデータ関数の引数、control.parent
は 最初 null で取得されるため、
if 分岐で 処理する必要がある、ということです。
この実装を進めた場合、エラーの状態は password2.errors
のように項目から取得することができます。
参考
demo
Discussion