遍历嵌套的表单组并将每个表单控件值更改为 null,如果它有模式错误

Loop through nested formgroup and change each form control value to null if it has pattern error

我必须查明我的表单控件是否有模式错误。如果它有模式错误,那么我必须将该 formcontrol 的值更改为 null。

我写了一个递归方法,它调用自身来检查表单控件是否有一个模式错误,然后它最终 return 是真还是假,但我想要的是改变它的值表单控件为 null

这是我的递归函数,

hasPatternError(form: AbstractControl, isRecursion = false): boolean {
        if (!isRecursion) {
            this.patternErrors = [];
        }
        if (form instanceof FormControl) {
            return form.hasError('pattern') === true ?? null;
        }
        if (form instanceof FormArray) {
            form?.controls?.forEach(e => {
                this.hasAnyPatternError(e, true);
            });
        }
        if (form instanceof FormGroup) {
            Object.keys(form.controls).forEach(key => {
                const error = this.hasAnyPatternError(form.get(key), true);
                if (error === true) {
                    this.patternErrors.push(error);
                }
            });
            return this.patternErrors.length > 0 ? true : false;
        }
}

这是我的表单,正在监听值变化事件。在 change 事件中,我调用上面的递归方法来查找是否有任何表单控件有模式错误,但坚持将该表单控件的值更改为 null。

注意:我希望方法 (hasPatternError) return 一个对象(将错误转换为 null 并且不希望表单实时更改)

ngOnInit() {
    this.myForm = this.fb.group({
      name: [''],
      address: this.fb.group({
        street: [''],
        zip: [''],
        licenseNo: ['', [Validators.required, Validators.pattern(/^[a-z0-9]{10}$/i)]],
      })
    })
    this.myForm.valueChanges.subscribe(
      data => {
        console.log(this.hasAnyPatternError(this.myForm))
      }
    );
  }

这是我在 stackblitz

上的 code

当您推送错误时,您已经引用了 form 和控件 key

设置当时控件上的值。

  • 因为你是用递归来做的,所以看起来有些奇怪 我在你的 stackblitz 中玩它时的行为。
  • 但是我想说的是,控件上有一个setValue功能,只需要 以确定在您的逻辑中使用它的最佳方式。
  • 甚至可能需要探索去抖动等行为,让用户有时间完成击键。

if (!form.controls[key]['controls'] && error === true) {
                    setTimeout(()=>{
                      form.controls[key].setValue('');
                    },3000)
                    this.patternErrors.push(error);
                }

我添加了一个 setTimeout 等待 3 秒,然后再将值设置回 '' 以模拟去抖...它似乎有效,但这不是一个合适的解决方案,只是说明了原理您需要探索如何在递归中正确利用 setValue

STACKBLITZ

https://stackblitz.com/edit/ng-nested-formgroup-zet7ry?file=src/app/app.component.ts

不是 return 表示模式错误的布尔值,而是 return 有模式错误的控件。

findPatternErrors(formItem: AbstractControl): FormControl[] {
  if (formItem instanceof FormControl) {
    if (formItem.hasError('pattern')) {
      return [formItem];
    } 
    return [];
  } 

  if (formItem instanceof FormArray) {
    const patternErrors: FormControl[] = [];
    formItem.controls?.forEach(arrayItem => {
      const ctrls = this.findPatternErrors(arrayItem);
      Array.prototype.push.apply(patternErrors, ctrls);
    });
    return patternErrors;
  }

  if (formItem instanceof FormGroup) {
    const patternErrors: FormControl[] = [];
    Object.keys(formItem.controls).forEach(key => {
      const ctrls = this.findPatternErrors(formItem.get(key));
      if (ctrls.length) {
        Array.prototype.push.apply(patternErrors, ctrls);
      }
    });
    return patternErrors;
  }
}

https://stackblitz.com/edit/ng-nested-formgroup-fmhfcs?file=src/app/app.component.ts