【问题标题】:Send a custom form control validator a FormArray向自定义表单控件验证器发送 FormArray
【发布时间】:2019-07-09 15:36:31
【问题描述】:

我只是尝试验证控件的值是否与 FormArray 中的值匹配。

我想明确一点,我不想验证表单、FormGroup 或 FormArray。这个问题是为了学习如何将参数传递给验证器函数和addValue控件的验证。

这是我的自定义验证服务中的内容:

public form: FormGroup = this.fb.group({
    addValue: this.fb.control(null, [this.validatorService.duplicate(this.form.get('values'))]),
    values: this.fb.array([])
});

还有验证器功能

public duplicate(values: FormArray): ValidatorFn {
    return (control: AbstractControl): { [key: string]: boolean } | null => {
        for (let i = 0, j = values.length; i < j; i++ ) {
            if (control.value === values[i].value) {
                return { 'duplicate': true };
            }
        }
        return null;
    };
}

此时我收到一个错误,我使用 FormArray 作为参数添加验证器:

“AbstractControl”类型的参数不可分配给 键入“表单数组”。类型“AbstractControl”缺少以下内容 “FormArray”类型的属性:控件、at、push、insert 和 5 more.ts(2345) (属性) FormGroup.controls: { [键:字符串]:AbstractControl; }

谁能告诉我如何将 FormArray 发送到验证器函数中?

这里是验证器的Stackblitz 没有得到 FormArray

【问题讨论】:

    标签: javascript angular validation angular-reactive-forms


    【解决方案1】:

    AbstractControl 是基类,只需转换它:

    public form: FormGroup = this.fb.group({
        addValue: this.fb.control(null, [this.validatorService.duplicate(this.form.get('values') as FormArray)]),
        values: this.fb.array([])
    });
    

    你也可以直接发送值:

    this.validatorService.duplicate(this.form ? this.form.get('values').value : []);
    

    public duplicate(values: string[]): ValidatorFn {
        return (control: AbstractControl): { [key: string]: boolean } | null => {
            for (let i = 0, j = values.length; i < j; i++ ) {
                if (control.value === values[i]) {
                    return { 'duplicate': true };
                }
            }
            return null;
        };
    }
    

    新答案

    改为添加表单验证器:

    this.form = this.fb.group({
      addValue: this.fb.control(null),
      values: this.fb.array(['test2', 'test3'])
    }, { validator: this.validatorService.duplicate2 });
    

    使用此代码:

    public duplicate2(control: AbstractControl): ValidationErrors | null {
        const newValue = control.get('addValue') ? control.get('addValue').value : null;
        const values = control.get('values') ? control.get('values').value : [];
    
        console.log("1 " + newValue);
        console.log(values);
        for (let i = 0, j = values.length; i < j; i++ ) {
                  if (newValue === values[i]) {
                      return { 'duplicate2': true };
                  }
              }
              return null;          
      }
    

    并更改您的验证:

    <app-validator [control]="form"></app-validator>
    

    https://stackblitz.com/edit/send-validator-formarray-l8j7ys

    您可以将字段名称作为参数传递给验证器。

    【讨论】:

    • 访问values 似乎导致了一个未定义的错误:TypeError: Cannot read property 'get' of undefined 我有点难过。我稍后尝试添加 addValue 控件以查看是否有帮助并再次从我的问题中得到原始错误。
    • 三元法导致Argument of type 'undefined[] | FormArray' is not assignable to parameter of type 'FormArray'.
    • @TR3B 如前所述,我将验证函数参数更改为数组...如果要保留 formArray,请发送 null 或 new FormArray (this.form ? this.form.get( '值').value : null)
    • 是的,不发送数组到验证器stackblitz.com/edit/send-validator-formarray
    • @TR3B 如前所述,您可以更改方法以添加 FormArray 的名称作为参数并使用它来查找 FormArray... 否则,在控件上它只能在静态上工作列表,而不是 formArray。
    【解决方案2】:

    您正在尝试访问尚未实例化的 FormArray:

        this.form = this.fb.group({
      addValue: this.fb.control(null, [this.validatorService.duplicate(this.form ? this.form.get('values').value : []), Validators.minLength(2)]),
      values: this.fb.array([])
    });
    

    要解决这个问题,你必须选择:

    1) 先实例化FormArray
    2) 实例化FormGroup后添加验证器

    【讨论】:

    • 是的,我也试过了。在我们创建表单后添加验证器不起作用。欢迎您试用 StackBlitz?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-06
    • 1970-01-01
    • 2022-01-02
    • 2020-01-07
    • 1970-01-01
    相关资源
    最近更新 更多