Angular FormArray自定义验证器未触发

时间:2020-08-26 10:03:03

标签: angular validation angular-reactive-forms

在我的FormGroup中,有一个FormArray,其中将包含n个FormControl,这些FormControl中的每一个都附加有一个电子邮件验证程序。

我希望我的FormArray能够知道任何FormControl是否存在电子邮件验证错误,如果是,则FormError errors属性应设置为{email: true}

为此,我编写了一个应用于我的FormArray的自定义验证器。但是,当在FormArray中添加或删除FormControl元素时,此验证器似乎无法正确触发。

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

此表单数组由子组件控制,该子组件具有对formArray的引用,该组件在实例化时作为输入传递给它。子组件中向formArray添加值的方法是

  pushToFormcontrol(value: any) {
    if(!this.fArray.value.includes(value)){
      if(this.usesAutocomplete){
        if(this.autocompleteData.some(el => el === value)) {
          this.fArray.push(this.formBuilder.control(value));
          this.filterAutocomplete();
          this.clearInput();
        }
      } else {
          this.fArray.push(this.formBuilder.control(value, [Validators.email]));
          this.clearInput();
      }
    }
    this.fArray.markAsDirty();
  }

我的FormArray的自定义验证器是

export function alertContactsArrayValidator(): ValidatorFn {
  return (formArray: FormArray): { [key: string]: any } | null => {
    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;
  };
}

如果我在浏览器中调试代码,我可以看到外部的alertContactsArrayValidator函数已进入其中,但是返回的内部函数从未被激活。我也从未看到任何控制台日志。

编辑

经过进一步的实验,我发现了一些有趣的东西。如果我修改FormArray以便插入一个空数组而不是this.alertData.alertContacts(它是一个字符串数组),那么验证器将完美工作。我开始认为这与我创建FormArray的方式有关。

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

如果我想用已经在其中的元素实例化FormArray,我是否应该以不同于仅将数组作为this.formBuilder.array()方法的第一个参数传递的方式来实现它?

1 个答案:

答案 0 :(得分:0)

Validator不同,ValidatorFn应该手动触发(Angular不会自行调用以让您通过一些有用的配置),如下所示:

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

编辑:

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