【问题标题】:Angular - assign custom validator to a FormGroupAngular - 将自定义验证器分配给 FormGroup
【发布时间】:2018-12-08 04:49:12
【问题描述】:

我需要将自定义验证器分配给 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;
      }
}

我有一种情况,我需要在实例化 FormGroup 之后添加自定义验证器,所以我尝试在实例化 myForm 之后执行此操作,而不是添加验证器当窗体实例化时:

let myForm : FormGroup;

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

this.myForm.validator = this.comparisonValidator;

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

Type '(g: FormGroup) => void' is not assignable to type 'ValidatorFn'.
  Type 'void' is not assignable to type 'ValidationErrors'.

如何为我的FormGroup 分配一个验证器,以便将formGroup 作为参数传递给我的comparisonValidator 函数?

更新 - 我在comparisonValidator 中添加了一行显示我正在执行setErrors 的位置,以便更清楚地了解我是如何尝试设置验证错误的。

【问题讨论】:

  • 可以使用setValidators()添加动态验证器。但特定于特定控件,您可以一次更新
  • 您收到此错误是因为您从 comparisonValidator 函数返回 void。更改函数以在最后一行(不在 if 语句内)返回 null,错误应该消失了。

标签: javascript angular typescript angular-reactive-forms angular-validation


【解决方案1】:

我创建了一个stackblitz 看看。

在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;
    };
 }
}

在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>

【讨论】:

  • 谢谢阿努拉达。为了澄清我在问什么,我试图只添加验证器 after FormGroup 被实例化,而不是添加它 when 表单被实例化。我对问题进行了一些编辑以使其更清楚。
  • @ChrisHalcrow 我已经更新了答案。 nd 您可以在here 中找到一个工作示例。
【解决方案2】:

要在实例化 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;
  }

You can play here.

【讨论】:

  • 比从验证器返回任何更好的解决方案。
【解决方案3】:

感谢@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 });
      }
}

【讨论】:

    【解决方案4】:

    删除所有表单控件空白表单表单组

    自定义验证器:

        export function formGroupRemoveWhitespaceValidator(form: FormGroup): ValidationErrors | null {
        const keys: string[] = Object.keys(form.controls);
    
        if (keys.length) {
            keys.forEach(k => {
                let control = form.controls[k];
                
                if (control && control.value && !control.value.replace(/\s/g, '').length) {
                    control.setValue('');
                }
            });
        }
    
        return null;
    }
    

    组件:

    let myForm : FormGroup;
    
    myForm = this.formBuilder.group({
               myControl1: defaultValue,
               myControl2: defaultValue
             }, { validators: formGroupRemoveWhitespaceValidator });
    

    【讨论】:

      猜你喜欢
      • 2021-06-24
      • 2018-08-20
      • 2019-02-12
      • 2018-01-12
      • 2018-04-23
      • 2018-07-10
      • 2019-01-07
      • 2017-04-04
      • 2018-05-23
      相关资源
      最近更新 更多