Angular 4アプリには、次のようなフォームモデルがあります。
this.form = this._fb.group({
title: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(50)]],
description: ['', [Validators.required, Validators.minLength(3)]]
});
今私が欲しいのは、コントロールバリデータ配列から必要なバリデータのみを動的に削除することです。このようなもの:
saveDraft() {
this.form.controls['title'].removeValidator('required'); //Just a fake implementation for demonstration
}
この質問は、前述の質問の複製ではありません。私の場合は異なります。必要なバリデータを知らないうちに削除したいだけです。
検証を追加する場合は、これを試してください。
saveDraft() {
this.form.get('title').setValidators([Validators.required, Validators.minLength(3)]);
this.form.get('title').updateValueAndValidity();
}
バリデータを削除する場合は、これを試してください。
saveDraft() {
this.form.get('title').clearValidators();
this.form.get('title').updateValueAndValidity();
}
バリデータをクリアして設定するのは好きではありません。動的な「必須」バリデータを得るために、すべての静的バリデータ(パターン、最小、最大など)を繰り返す必要があるからです。
条件付きバリデーターを使用します。
export function conditionalValidator(condFn: (control: AbstractControl) => boolean,
validators: ValidatorFn | ValidatorFn[]): ValidatorFn {
return (control) => {
if (!condFn(control)) {
return null;
}
if (!Array.isArray(validators)) {
return validators(control);
}
return validators.map(v => v(control)).reduce((errors, result) =>
result === null ? errors :
(Object.assign(errors || {}, result))
);
};
}
次に、静的なバリデーターを動的な「必須」条件と組み合わせることができます。
this.fb.group({name: ['', [Validators.minLength(4),
conditionalValidator(this.isClientProj, Validators.required)]]}
isClientProj()
は条件関数(クロージャー)です
残念ながら、この時点ではAngularにはremoveValidator機能がありません。できることは、削除したいバリデータなしでバリデータを再設定することだけです。そのため、どのバリデータを削除したいかではなく、どのバリデータを保持したいかを知る必要があります。したがって、この:
this.form.get('title').setValidators([Validators.minLength(3), Validators.maxLength(50)]);
削除機能に最も近いものです。 formcontrol上の現在のバリデータにアクセスして、独自の削除関数を作成しようとすることもできません。最善の方法は、特定のコントロールのバリデータを追跡して管理できる独自のフォームコントロール検証マネージャクラスを記述することです。
バリデーターを追加するには:
this.form = this._fb.group({
title: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(50)]],
description: ['', [Validators.required, Validators.minLength(3)]]
});
または
this.form.get('title').setValidators([Validators.required,Validators.minLength(3), Validators.maxLength(50)]);
「必須」バリデータのみを削除するには、バリデータをリセットできます。
saveDraft() {
this.form.get('title').setValidators([Validators.minLength(3), Validators.maxLength(50)]);
this.form.get('title').updateValueAndValidity();
}
pdateValueAndValidityは、コントロールが変更を伝播し、値とバリデーターが変更されたときにイベントを発行する方法を決定します
setValidatorsを使用して検証を削除できます。
this.form.get('title').setValidators(null);
this.form.get('title').setErrors(null);
エントリをドラフトとして保存するときに同じ問題が発生し、次の解決策を準備しました。
@Component({
// ...
})
export class FormComponent{
form: FormGroup;
constructor(private fb: FormBuilder){
this.form = this.fb.group({
name: ['', Validators.required, Validators.maxLength(20)],
description: ['', Validators.required, Validators.maxLength(200)],
address: this.fb.group({
line1: ['', Validators.required, Validators.maxLength(100)],
line2: ['', Validators.maxLength(100)]
})
});
}
validateDraft(formElement: FormGroup | FormArray | FormControl): boolean {
let result = true;
Object.keys(formElement.controls).forEach(field => {
const control = formElement.get(field);
if(control instanceof FormControl) {
control.markAsTouched({ onlySelf: true });
if(control.errors && control.errors['required']) {
control.markAsUntouched({ onlySelf: true });
}
else if(control.invalid) {
result = false;
}
} else if (control instanceof FormArray) {
if (!this.validateDraft(control)) {
result = false;
}
}else if (control instanceof FormGroup) {
if (!this.validateDraft(control)) {
result = false;
}
}
});
}
saveDraft(){
if(this.validateDraft(this.form)){
//save draft - ignore required errors
}
}
save(){
if(this.form.valid){
//save
}
}
}