Angular 为 FormArray 提供除空数组以外的任何内容时自定义验证器中断

Angular custom validator breaks when providing FormArray with anything other than empty array

我有一个与我的 FormArray 一起使用的自定义验证器,只要 FormArray 的输入是 [],验证器就可以正常工作。但是,如果我为 FormArray 提供 string[]FormControl[],验证器将破坏整个 angular 应用程序并导致无限循环错误。

我真的不确定是什么导致了这种情况发生。我需要能够用元素实例化 FormArray,所以我需要它才能工作。

起初我认为问题是由于我将 string[] 传递给 FormArray 而不是 FormControl[],但即使在将数组映射到 FormControls 数组之后我得到同样的问题。

this.alertData.alertContacts 只是一个电子邮件字符串数组。

FormGroup 实例化 - 有效

this.form = this.formBuilder.group({
      alertContacts: this.formBuilder.array([], [Validators.required, alertContactsArrayValidator()]),
    });

FormGroup 实例化 - 损坏

this.form = this.formBuilder.group({
      alertContacts: this.formBuilder.array(this.alertData.alertContacts, [Validators.required, alertContactsArrayValidator()]),
    });

FormGroup 实例化 - 损坏

this.form = this.formBuilder.group({
      alertContacts: this.formBuilder.array(this.alertData.alertContacts.map(x => new FormControl(x)), [Validators.required, alertContactsArrayValidator()]),
    });

自定义验证器

export function alertContactsArrayValidator(): ValidatorFn {
  return (c: AbstractControl): { [key: string]: any } | null => {
    let formArray = <FormArray>c;
    console.log(formArray);
    let hasEmailErrors = false;
    let formControls = formArray.controls;
    console.log(formControls);
    formControls.forEach(control => {
      let controlErrors: ValidationErrors = control.errors;
      console.log("Current control errors: ", controlErrors);
      Object.keys(controlErrors).forEach(key => {
        if (key === 'email') {
          hasEmailErrors = true;
          console.log("key has email");
        }
      });
    });
    return hasEmailErrors ? {'email': true} : null;
  };
}

您需要检查 control.errors 是否为空。

formControls.forEach(control => {
      let controlErrors: ValidationErrors = control.errors;
      if (controlErrors){ //<---this "if"
        Object.keys(controlErrors).forEach(key => {
          if (key === 'email') {
            hasEmailErrors = true;
            console.log("key has email");
          }
        });
      }
    });

你也可以更简单

formControls.forEach(control => {
   if (control.errors && control.errors.email){
        hasEmailErrors = true;
        console.log("key has email");
   }
});

甚至

formControls.forEach(control => {
   hasEmailErrors = hasEmailErrors ||
      (control.errors && control.errors.email)
   }
});

注意:我想你想要

this.form = this.formBuilder.group({
      alertContacts: this.formBuilder.array(this.alertData.alertContacts
       .map(x => new FormControl(x,[Validators.required,Validators.email])),
            [alertContactsArrayValidator()]),
    });

FormsControls 需要电子邮件验证器和自定义验证器数组