web-dev-qa-db-ja.com

Angular 4必要なバリデーターを条件付きで削除します

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
}

この質問は、前述の質問の複製ではありません。私の場合は異なります。必要なバリデータを知らないうちに削除したいだけです。

24
Ali Shahzad

検証を追加する場合は、これを試してください。

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();
}
63
Singam

バリデータをクリアして設定するのは好きではありません。動的な「必須」バリデータを得るために、すべての静的バリデータ(パターン、最小、最大など)を繰り返す必要があるからです。

条件付きバリデーターを使用します。

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()は条件関数(クロージャー)です

3
Alex R

残念ながら、この時点ではAngularにはremoveValidator機能がありません。できることは、削除したいバリデータなしでバリデータを再設定することだけです。そのため、どのバリデータを削除したいかではなく、どのバリデータを保持したいかを知る必要があります。したがって、この:

this.form.get('title').setValidators([Validators.minLength(3), Validators.maxLength(50)]);

削除機能に最も近いものです。 formcontrol上の現在のバリデータにアクセスして、独自の削除関数を作成しようとすることもできません。最善の方法は、特定のコントロールのバリデータを追跡して管理できる独自のフォームコントロール検証マネージャクラスを記述することです。

1
bryan60

バリデーターを追加するには:

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); 
0

エントリをドラフトとして保存するときに同じ問題が発生し、次の解決策を準備しました。

@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
        }
    }
}
0
kalinowski