角度でマルチコントロールカスタムバリデータを作成する
23963 ワード
角の反応形式ライブラリのカスタムバリデータは、開発者がより良いフォームUI/UXを作成しなければならない最も強力な(そして、私の意見で見落とされる)ツールのうちの1つです.カスタムバリデータは、単一のコントロールに限られていません.グループ全体を評価するのは簡単です.これは、複数のコントロールを比較するために最適です.この記事では、2つのフィールドを検証するマルチコントロールカスタムバリデータを作成します.
私がprevious article about custom validatorsで述べたように、組み込みのバリデータがそうでないカスタムロジックを処理し、1つの場所に妥当性検査エラーメッセージを作成することができます.これは、カスタムバリデータを強力かつ非常に再利用可能になります.
マルチコントロールカスタムバリデータの作成は、単一のコントロールの作成に非常に似ています.バリデータは、
フォームコントロールから値の変数を作成します.一度私はそれらを持って、私はいくつかの簡単な条件を設定します.
他のカスタムバリデータと同様に、マルチコントロールカスタムバリデータをテストするのは簡単です.このバリデータのためのライティング・ユニットテストは、私が最初に処理していなかったエッジ・ケースを見つけて、扱うのを助けました.以下に例を示します.
リポジトリは、所望の動作をダイヤルするのに役立つunit tests for the validatorを含んでいます.HereはGitthubのリポジトリです、そして、hereはStackblitzの上でコードの作業デモです.角の私のポストの全てはタグ付けされて、hereを集めました.
Creating a Multi-Control Custom Validator in Angular年には、Hapax Legomenonが初めて登場した.
私がprevious article about custom validatorsで述べたように、組み込みのバリデータがそうでないカスタムロジックを処理し、1つの場所に妥当性検査エラーメッセージを作成することができます.これは、カスタムバリデータを強力かつ非常に再利用可能になります.
マルチコントロールカスタムバリデータの作成
マルチコントロールカスタムバリデータの作成は、単一のコントロールの作成に非常に似ています.バリデータは、
AbstractControl
パラメーターで渡される必要があります.単一の制御バリデータでは、通常、制御は FormControl
です.しかし、マルチコントロールバリデータの場合は、コントロールとして親 FormGroup
に渡す必要があります.これを行うと、FormGroup
の内部のすべての子供たちのコントロールの範囲を私に与えます.このバリデータを再利用可能にするために、私は比較したいコントロールの名前も渡します.私はまた、エラーメッセージをより動的にするために比較している値の種類の名前を渡すことができます.フォームコントロールから値の変数を作成します.一度私はそれらを持って、私はいくつかの簡単な条件を設定します.
FormGroup
としてAbstractControl
として通過したので、FormControl
にエラーを設定したいならば、 FormControls
を特定のコントロールに呼び出す必要があります.さもなければ、私が setErrors()
を返すならば、彼らはValidationErrors
に適用されます.export class MatchFieldValidator {
static validFieldMatch(
controlName: string,
confirmControlName: string,
fieldName: string = 'Password',
): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const controlValue: unknown | null = control.get(controlName)?.value;
const confirmControlValue: unknown | null = control.get(
confirmControlName,
)?.value;
if (!confirmControlValue) {
control.get(confirmControlName)?.setErrors({
confirmFieldRequired: `Confirm ${fieldName} is required.`,
});
}
if (controlValue !== confirmControlValue) {
control
.get(confirmControlName)
?.setErrors({ fieldsMismatched: `${fieldName} fields do not match.` });
}
if (controlValue && controlValue === confirmControlValue) {
control.get(confirmControlName)?.setErrors(null);
}
return null;
};
}
}
作業バリデーターを持っているので、コンポーネントに配線する必要があります.複数のFormGroup
と対話したいので、親242479142にバリデータを付ける必要があります. FormControls
は、コントロールの設定の後にオプション引数を受け取ります.私はマッチフィールドバリデータを、コントロールの名前と比較して、比較するフィールドの種類を追加します.私は以下のコードを単純に関連するものに集中させました.private createForm(): FormGroup {
const form = this.fb.group({
password: [
'',
Validators.compose([PasswordValidator.validPassword(true)]),
],
confirmPassword: [''],
},
{
validators: Validators.compose([
MatchFieldValidator.validFieldMatch('password', 'confirmPassword', 'Password'),
]),
});
return form;
}
今の検証を行っているので、エラーをテンプレートにバインドできます.私はまだ簡単にFormGroup
を介してエラーオブジェクトを介してループを使用しています.<div class="field-group">
<mat-form-field>
<input
name="password"
id="password"
type="password"
matInput
placeholder="Password"
formControlName="password"
/>
<mat-error *ngIf="form.get('password')?.errors">
<ng-container *ngFor="let error of form.get('password')?.errors | keyvalue">
<div *ngIf="error.key !== 'required'">{{ error.value }}</div>
</ng-container>
</mat-error>
</mat-form-field>
<mat-form-field>
<input
name="confirmPassword"
id="confirmPassword"
type="password"
matInput
placeholder="Confirm Password"
formControlName="confirmPassword"
required
/>
<mat-error *ngIf="form.get('confirmPassword')?.errors">
<ng-container *ngFor="let error of form.get('confirmPassword')?.errors | keyvalue">
<div *ngIf="error.key !== 'required'">{{ error.value }}</div>
</ng-container>
</mat-error>
</mat-form-field>
</div>
バリデータのテスト
他のカスタムバリデータと同様に、マルチコントロールカスタムバリデータをテストするのは簡単です.このバリデータのためのライティング・ユニットテストは、私が最初に処理していなかったエッジ・ケースを見つけて、扱うのを助けました.以下に例を示します.
describe('validFieldMatch() default field name', () => {
const matchFieldValidator = MatchFieldValidator.validFieldMatch(
'controlName',
'confirmControlName',
);
const form = new FormGroup({
controlName: new FormControl(''),
confirmControlName: new FormControl(''),
});
const controlName = form.get('controlName');
const confirmControlName = form.get('confirmControlName');
it(`should set control error as { confirmFieldRequired: 'Confirm Password is required.' } when value is an empty string`, () => {
controlName?.setValue('');
confirmControlName?.setValue('');
matchFieldValidator(form);
const expectedValue = {
confirmFieldRequired: 'Confirm Password is required.',
};
expect(confirmControlName?.errors).toEqual(expectedValue);
});
it(`should set control error as { fieldsMismatched: 'Password fields do not match.' } when values do not match`, () => {
controlName?.setValue('password123!');
confirmControlName?.setValue('password123');
matchFieldValidator(form);
const expectedValue = {
fieldsMismatched: 'Password fields do not match.',
};
expect(confirmControlName?.errors).toEqual(expectedValue);
});
it(`should set control error as null when values match`, () => {
controlName?.setValue('password123!');
confirmControlName?.setValue('password123!');
matchFieldValidator(form);
expect(controlName?.errors).toEqual(null);
expect(confirmControlName?.errors).toEqual(null);
});
it(`should set control error as null when control matches confirm after not matching`, () => {
controlName?.setValue('password123!');
confirmControlName?.setValue('password123!');
matchFieldValidator(form);
controlName?.setValue('password123');
matchFieldValidator(form);
controlName?.setValue('password123!');
matchFieldValidator(form);
expect(controlName?.errors).toEqual(null);
expect(confirmControlName?.errors).toEqual(null);
});
it(`should set control error as null when confirm matches control after not matching`, () => {
controlName?.setValue('password123!');
confirmControlName?.setValue('password123!');
matchFieldValidator(form);
controlName?.setValue('password123');
matchFieldValidator(form);
confirmControlName?.setValue('password123');
matchFieldValidator(form);
expect(controlName?.errors).toEqual(null);
expect(confirmControlName?.errors).toEqual(null);
});
});
カスタムバリデータを作成し、非常に強力です.彼らは任意のレベルの反応形式で行うことができますので、複数のコントロールと対話することができますこのようなマルチコントロールカスタムバリデータを作成することが可能です.これは、開発者は非常に反応性のUI/UXのユーザーをクラフトすることができます.資源
リポジトリは、所望の動作をダイヤルするのに役立つunit tests for the validatorを含んでいます.HereはGitthubのリポジトリです、そして、hereはStackblitzの上でコードの作業デモです.角の私のポストの全てはタグ付けされて、hereを集めました.
Creating a Multi-Control Custom Validator in Angular年には、Hapax Legomenonが初めて登場した.
Reference
この問題について(角度でマルチコントロールカスタムバリデータを作成する), 我々は、より多くの情報をここで見つけました https://dev.to/karvel/creating-a-multi-control-custom-validator-in-angular-ifテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol