繁体   English   中英

在Angular 2/4中自动填充反应式表单控件的错误

[英]Automatically populate errors for reactive form controls in Angular 2/4

我在前端和后端都进行了验证。 前端的一切都没问题,但我无法在前端处理后端验证(根据后端验证手动将控件标记为无效)。

问题在于填充带有错误的表单控件,看起来我不能只this.formBuiltWithFormBuilder.setErrors()并传递一个有错误的对象来自动填充表单中包含的所有控件 - 因为当所有字段状态保持this.formBuiltWithFormBuilder.setErrors()时,只有表单变为无效相同。

所以目前我正在尝试做类似的事情:

// Example of incoming formErrors:
// (it can also be nested for nested forms)
// {
//    phone: {
//      phoneNumberNoMatch: "The input does not match..."
//    }
// }

@Input() public formErrors: ValidationErrors;
public detailsForm: FormGroup;

public ngOnInit() {
  this.createForm();
}

public ngOnChanges() {
  this.updateFormErrors(this.formErrors);
}

private createForm(account: AccountInterface) {
  this.detailsForm = this.fb.group({
    firstName: ['', Validators.required],
    lastName: ['', Validators.required]
  });
}

private updateFormErrors(errors: any) {
  if (this.detailsForm) {
    // Trying to populate included form controls with errors
    this.detailsForm.setErrors(errors);
  }
}

```

我还考虑过遍历错误对象并为每个控件手动应用错误,但我认为这个解决方案并不理想,因为可能存在嵌套表单。

那么它是一种自动填充错误的表单控件的方法吗?

看起来没有内置的解决方案,所以我创建了一个表单助手类来填充错误。 理论上它也应该填充嵌套/数组形式,但我只测试了它的普通形式。 如果没有,请告诉我;)

它使用lodash/map方法遍历errors对象。

import { FormGroup, FormControl, FormArray } from '@angular/forms';
import { map } from 'lodash';

export class FormHelper {
  public static POPULATE_FORM_GROUP_ERRORS(
    rootFormGroup: FormGroup,
    errors: any
  ) {
    map(rootFormGroup.controls, (control, name) => {
      if (control instanceof FormControl) {
        if (errors.hasOwnProperty(name)) {
          control.setErrors(errors[name]);
        }
      }
      if (control instanceof FormGroup) {
        if (errors.hasOwnProperty(name)) {
          FormHelper.POPULATE_FORM_GROUP_ERRORS(control, errors[name]);
        }
      }
      if (control instanceof FormArray) {
        if (errors.hasOwnProperty(name) && errors[name] instanceof Array) {
          this.iterateOverFormArrayControl(control, errors[name]);
        }
      }
    });
  }

  private static iterateOverFormArrayControl(
    formArray: FormArray, 
    errors: any[]
  ) {
    errors.forEach((error: any, index: number) => {
      const arrayControl = formArray.at(index);
      if (arrayControl && arrayControl instanceof FormControl) {
        arrayControl.setErrors(error);
      }
      if (arrayControl && arrayControl instanceof FormGroup) {
        FormHelper.POPULATE_FORM_GROUP_ERRORS(arrayControl, error);
      }
      if (arrayControl && arrayControl instanceof FormArray && error instanceof Array) {
        FormHelper.iterateOverFormArrayControl(arrayControl, error);
      }
    });
  }
}

所以现在我的表单看起来像:

// ... Somewhere at the top
import { FormHelper } from '@app/commons/FormHelper';
// ...

// Example of incoming formErrors:
// (it can also be nested for nested forms)
// {
//    phone: {
//      phoneNumberNoMatch: "The input does not match..."
//    }
// }

@Input() public formErrors: ValidationErrors;
public detailsForm: FormGroup;

public ngOnInit() {
  this.createForm();
}

public ngOnChanges() {
  this.updateFormErrors(this.formErrors);
}

private createForm(account: AccountInterface) {
  this.detailsForm = this.fb.group({
    firstName: ['', Validators.required],
    lastName: ['', Validators.required]
  });
}

private updateFormErrors(errors: any) {
  if (this.detailsForm) {
    // Populate included form controls with errors
   FormHelper.POPULATE_FORM_GROUP_ERRORS(this.detailsForm, errors);
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM