角度-将自定义验证器分配给FormGroup

Chr*_*row 9 javascript typescript angular-validation angular angular-reactive-forms

我需要将自定义验证器分配给FormGroup。我可以像这样创建FormGroup时执行此操作:

let myForm : FormGroup;

myForm = this.formBuilder.group({
        myControl1: defaultValue,
        myControl2: defaultValue
      }, { validator: this.comparisonValidator })

comparisonValidator(g: FormGroup) {
      if (g.get('myControl1').value > g.get('myControl2'.value)) {
        g.controls['myControl1'].setErrors({ 'value2GreaterThanValue1': true });
        return;
      }
}
Run Code Online (Sandbox Code Playgroud)

我遇到一种情况,尽管在实例化FormGroup 之后需要添加自定义验证器,所以我尝试在实例化之后执行此操作myForm,而不是在实例化表单时添加验证器:

let myForm : FormGroup;

myForm = this.formBuilder.group({
        myControl1: defaultValue,
        myControl2: defaultValue
      })

this.myForm.validator = this.comparisonValidator;
Run Code Online (Sandbox Code Playgroud)

这给了我一个编译器错误:

Type '(g: FormGroup) => void' is not assignable to type 'ValidatorFn'.
  Type 'void' is not assignable to type 'ValidationErrors'.
Run Code Online (Sandbox Code Playgroud)

我如何验证程序分配给我FormGroup,以便formGroup作为参数来传递我的comparisonValidator功能?

更新 -我添加了一行以显示我在setErrors中的位置comparisonValidator,以更清楚地说明我要如何设置验证错误。

Anu*_*ara 13

我创建了一个堆栈闪电看一下。

在component.ts文件中

import { Component } from '@angular/core';
import {FormBuilder,FormGroup, ValidationErrors, ValidatorFn} from '@angular/forms'

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  myForm: FormGroup;
  defaultValue = 20;

constructor(private formBuilder: FormBuilder) {
  this.myForm = this.formBuilder.group({
        myControl1: this.defaultValue,
        myControl2: this.defaultValue
      });
      debugger
      this.myForm.setValidators(this.comparisonValidator())
}

 public comparisonValidator() : ValidatorFn{
       return (group: FormGroup): ValidationErrors => {
          const control1 = group.controls['myControl1'];
          const control2 = group.controls['myControl2'];
          if (control1.value !== control2.value) {
             control2.setErrors({notEquivalent: true});
          } else {
             control2.setErrors(null);
          }
          return;
    };
 }
}
Run Code Online (Sandbox Code Playgroud)

在component.html文件中

<div>
  <form [formGroup]="myForm">
    <input formControlName="myControl1" type="number">
    <input formControlName="myControl2"  type="number">
    <br>Errors: {{myForm.get('myControl2').errors | json}}
  </form>
</div>
Run Code Online (Sandbox Code Playgroud)

  • `ValidatorFn` 不应该**返回**错误对象吗?在这种情况下,“ValidatorFn”调用“setErrors()”,但不会“返回”任何内容 (2认同)

Sha*_*aiz 6

要在实例化 formGroup 之后设置任何验证器(预定义或自定义),您需要使用FormGroup 的 setValiators()方法。例如:

  let myFormGroup = this.    _fb.group({
      control1: new FormControl('1', [])
    });
  myFormGroup.setValidators(this.customValidators());
  customValidators(): ValidatorFn {
   let myFun = (cc: FormGroup): ValidationErrors => {
     if(cc.valid) return null;
     else return {something: 'someError'};
   };
   return myFun;
  }
Run Code Online (Sandbox Code Playgroud)

你可以在这里玩。


Chr*_*row 5

感谢@Anuradha Gunasekara - 他的答案是最正确和最完整的解决方案。我的错误的“快速修复”只是any在验证器上添加返回类型。我仍然可以将自定义验证器分配给FormGroup,并且FormGroup将作为参数隐式传递给我的自定义验证器。此代码将起作用:

let myForm : FormGroup;

myForm = this.formBuilder.group({
           myControl1: defaultValue,
           myControl2: defaultValue
         })

this.myForm.validator = this.comparisonValidator;

comparisonValidator(g: FormGroup) : any {
      if (g.get('myControl1').value > g.get('myControl2'.value)) {
        g.controls['myControl1'].setErrors({ 'value2GreaterThanValue1': true });
      }
}
Run Code Online (Sandbox Code Playgroud)