【问题标题】:Angular FormArray custom validator not firingAngular FormArray 自定义验证器未触发
【发布时间】:2020-08-26 10:03:03
【问题描述】:

在我的 FormGroup 中有一个 FormArray,其中包含 n 个 FormControl,每个 FormControl 都附有一个电子邮件验证器。

我希望我的 FormArray 能够知道任何 FormControl 是否有电子邮件验证错误,如果是,则 FormError 错误属性应设置为 {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() 方法的第一个参数传递的方式来执行它?

【问题讨论】:

    标签: angular validation angular-reactive-forms


    【解决方案1】:

    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()
        ])),
      ),
    });
    

    【讨论】:

    • 看,我试过了。但是当我这样做时,我的应用程序陷入了无限的错误循环。我确实发现了一些东西。我将编辑 OP。
    • @Jake12342134 FormArray 接受 FormControl 的数组
    • 是否有一种简单的方法可以将字符串数组传递给 formBuilder.array 方法,或者我需要创建一个方法来将 string[] 转换为 FormControl[]
    • this.alertData.alertContacts.map(x => new FormControl(x))
    • 不起作用,我仍然得到这个导致无限循环的奇怪错误。
    猜你喜欢
    • 2020-03-06
    • 2020-05-29
    • 1970-01-01
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多