Angular 反应式表单和自定义验证器错误

Angular reactive forms and custom validator error

在我的 Angular 4 应用程序中,我有一个 custom form validator 看起来像这样:

import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';

export function myCustomValidator(myCustomArg: string): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {

    if (control.value) {
      // do some checks with control.value and myCustomArg
      // return error if needed
    }

    // return null otherwise
    control.setErrors(null);
    return null;
  };
}

但是当我尝试在我的 reactive forms 之一中使用它时:

  ngOnInit() {
    this.form = new FormGroup({
      'myControl': new FormControl(null, [ myCustomValidator(...) ]),
      // ...
    });
  }

我遇到了几个错误:

ERROR TypeError: Cannot read property 'emit' of undefined at FormControl.webpackJsonp.../../../forms/@angular/forms.es5.js.AbstractControl._updateControlsErrors (forms.es5.js:2836) at FormControl.webpackJsonp.../../../forms/@angular/forms.es5.js.AbstractControl.setErrors (forms.es5.js:2772) at file-extension.validator.ts:17 at forms.es5.js:506 at Array.map () at _executeValidators (forms.es5.js:506) at FormControl.validator (forms.es5.js:462) at FormControl.webpackJsonp.../../../forms/@angular/forms.es5.js.AbstractControl._runValidator (forms.es5.js:2720) at FormControl.webpackJsonp.../../../forms/@angular/forms.es5.js.AbstractControl.updateValueAndValidity (forms.es5.js:2688) at new FormControl (forms.es5.js:3011)


ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 0, nodeDef: {…}, elDef: {…}, elView: {…}}


ERROR Error: formGroup expects a FormGroup instance. Please pass one in.

但不幸的是,它们并不是很有帮助。

此问题与验证器分配给字段的方式有关。

事实上,验证器正在尝试访问控件的值 control.value

但是调用验证器工厂函数时,控件还不存在:

this.form = new FormGroup({
  'myControl': new FormControl(null, [ myCustomValidator(...) ]),
  // ...
});

所以为了解决这个问题,只需先创建表单然后然后分配验证器:

ngOnInit() {
   // first create the form with its controls
  this.form = new FormGroup({
    'myControl': new FormControl(null),
    // ...
  });

  // then assign the custom validator
  this.form.get('myControl').setValidators([
    myCustomValidator(...),
  ]);
}