typescript Angular -将自定义验证程序分配给窗体组

4jb9z9bj  于 2022-12-19  发布在  TypeScript
关注(0)|答案(5)|浏览(97)

我需要为FormGroup分配一个自定义验证器。我可以在创建FormGroup时这样做:

let myForm : FormGroup;

myForm = this.formBuilder.group({
        myControl1: defaultValue,
        myControl2: defaultValue
      }, { validator: this.comparisonValidator })

comparisonValidator(g: FormGroup) {
      if (g.get('myControl1').value > g.get('myControl2'.value)) {
        g.controls['myControl1'].setErrors({ 'value2GreaterThanValue1': true });
        return;
      }
}

但是我遇到了一种情况,我需要在示例化FormGroup * 之后 * 添加自定义验证器,所以我尝试在示例化myForm之后添加验证器,而不是在示例化表单时添加验证器:

let myForm : FormGroup;

myForm = this.formBuilder.group({
        myControl1: defaultValue,
        myControl2: defaultValue
      })

this.myForm.validator = this.comparisonValidator;

这给了我一个编译器错误:

Type '(g: FormGroup) => void' is not assignable to type 'ValidatorFn'.
  Type 'void' is not assignable to type 'ValidationErrors'.

如何为FormGroup分配验证器,以便formGroup作为参数传递给comparisonValidator函数?

更新-我添加了一行代码来显示我在comparisonValidator中执行setErrors的位置,以使我更清楚地尝试如何设置验证错误。

zengzsys

zengzsys1#

我创建了一个stackblitz,请看。
在组件.ts文件中

import { Component } from '@angular/core';
import {FormBuilder,FormGroup, ValidationErrors, ValidatorFn} from '@angular/forms'

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  myForm: FormGroup;
  defaultValue = 20;

constructor(private formBuilder: FormBuilder) {
  this.myForm = this.formBuilder.group({
        myControl1: this.defaultValue,
        myControl2: this.defaultValue
      });
      debugger
      this.myForm.setValidators(this.comparisonValidator())
}

 public comparisonValidator() : ValidatorFn{
       return (group: FormGroup): ValidationErrors => {
          const control1 = group.controls['myControl1'];
          const control2 = group.controls['myControl2'];
          if (control1.value !== control2.value) {
             control2.setErrors({notEquivalent: true});
          } else {
             control2.setErrors(null);
          }
          return;
    };
 }
}

在component.html文件中

<div>
  <form [formGroup]="myForm">
    <input formControlName="myControl1" type="number">
    <input formControlName="myControl2"  type="number">
    <br>Errors: {{myForm.get('myControl2').errors | json}}
  </form>
</div>
aemubtdh

aemubtdh2#

要在示例化formGroup之后设置任何验证器(预定义的或自定义的),您需要使用FormGroup的**setValidators()**方法。例如:

let myFormGroup = this.    _fb.group({
      control1: new FormControl('1', [])
    });
  myFormGroup.setValidators(this.customValidators());
  customValidators(): ValidatorFn {
   let myFun = (cc: FormGroup): ValidationErrors => {
     if(cc.valid) return null;
     else return {something: 'someError'};
   };
   return myFun;
  }
q3qa4bjr

q3qa4bjr3#

感谢@Anuradha Gunasekara -他的回答是最正确和完整的解决方案。我的错误的“快速修复”是在验证器上添加一个any返回类型。我仍然可以将自定义验证器赋值给FormGroup,并且FormGroup将作为参数隐式传递给我的自定义验证器。下面的代码将工作:

let myForm : FormGroup;

myForm = this.formBuilder.group({
           myControl1: defaultValue,
           myControl2: defaultValue
         })

this.myForm.validator = this.comparisonValidator;

comparisonValidator(g: FormGroup) : any {
      if (g.get('myControl1').value > g.get('myControl2'.value)) {
        g.controls['myControl1'].setErrors({ 'value2GreaterThanValue1': true });
      }
}
osh3o9ms

osh3o9ms4#

从窗体组中删除所有窗体控件白色
自定义验证器:

export function formGroupRemoveWhitespaceValidator(form: FormGroup): ValidationErrors | null {
    const keys: string[] = Object.keys(form.controls);

    if (keys.length) {
        keys.forEach(k => {
            let control = form.controls[k];
            
            if (control && control.value && !control.value.replace(/\s/g, '').length) {
                control.setValue('');
            }
        });
    }

    return null;
}

组件:

let myForm : FormGroup;

myForm = this.formBuilder.group({
           myControl1: defaultValue,
           myControl2: defaultValue
         }, { validators: formGroupRemoveWhitespaceValidator });
ecfdbz9o

ecfdbz9o5#

这些答案对我不起作用,因为我还有其他的验证器。在我的用例中,我必须为相反的字段设置错误。
也许它并不完全符合OP的要求,但它希望能帮助其他人(像我一样),降落在这个网站上。
这里是我的解决方案,它可以安全地与其他验证器组合,并确保相反的字段得到更新。

// ...
this.form = this.formBuilder.group({
        myControl1: this.formBuilder.control(defaultValue, [Validators.required, this.validateIsEqualTo('myControl2')]),
        myControl2: this.formBuilder.control(defaultValue, this.validateIsEqualTo('myControl1')
      });

this.form.get('myControl1').valueChanges
   .pipe(
      takeUntil(this.destroy$),
      disinctUntilChanged())
   .subscribe(() => this.form.get('myControl2').updateValueAndValidity());

this.form.get('myControl2').valueChanges
   .pipe(
      takeUntil(this.destroy$),
      disinctUntilChanged())
   .subscribe(() => this.form.get('myControl1').updateValueAndValidity());
// ...

public validateIsEqualTo(otherComponentId): ValidatorFn {
   return (control: FormControl): ValidationErrors => {
      const otherControl = this.form.get(otherComponentId);
      return control.value !== otherControl.value ? {notEquivalent: true} : null;
   }
}

相关问题