实现Angular跨字段验证的最佳方法

时间:2019-07-19 22:16:44

标签: angular angular-reactive-forms reactive-forms

我正在尝试找出在Angular中实现跨字段验证的最佳方法。

例如,我有一个选择字段,该字段使另一个字段成为必需字段。

我希望能够:

  • 更改字段的边框颜色(如果无效)
  • 在必填字段前在字段前显示**
  • 显示一条特定的错误消息,说明违反了哪些验证规则。

到目前为止,我想出了三种解决方案,但是它们对我来说并不那么令人信服。

  • 收听以选择字段更改并更新第二个字段的验证器。
  • 收听两个字段的更改并手动执行setErrors
  • 将验证转移到formGroup(由于验证状态现在存储在formGroup中,而不能直接在formControl中使用,因此会感到非常麻烦)。

这是一个Stackblitz实现,用于演示我的调查。

2 个答案:

答案 0 :(得分:1)

最好的方法是更简单的方法。只需使用

之类的customValidator
  form:FormGroup=new FormGroup({
    input1: new FormControl('optional'),
    input2: new FormControl(null,this.customValidator())
  })

  customValidator()
  {
    return ((control:any)=>{
      if (!control.parent)
        return null;

      let mandatory=control.parent.get('input1').value;
      return mandatory!='optional' && !control.value?{required:true}:null
    })
  }

另一个不要求control.parent的选项,它使用bind(this)。这样一来,我们就可以在验证器内部查看组件的所有变量,当然也可以访问this.form

  form:FormGroup=new FormGroup({
    input1: new FormControl('optional'),
    input2: new FormControl(null,this.customValidator().bind(this)) //<--bind(this)
  })

  customValidatorBind()
  {
    return ((control:any)=>{
      if (!this.form)
        return null;

      let mandatory=this.form.get('input1').value;
      return mandatory!='optional' && !control.value?{required:true}:null
    })
  }

好吧,我们希望在选中更改'input1''input2'时需要使用,在创建表单后,请订阅valueChanges

this.form.get('input1').valueChanges.subscribe(()=>{
  this.form.get('input2').updateValueAndValidity()
})

已更新 ,还有另一个方法。在窗体上创建customValidator并使用验证器将setError应用于所需的控件。使用setError,使Angular为我们添加ng-invalid,我们不需要订阅值更改。 见

    form:FormGroup=new FormGroup({
        input1: new FormControl('optional'),
        input2: new FormControl(null)
      },{validators:this.customValidatorForm()})

  customValidatorForm()
  {
    return (form:FormGroup)=>{
      const error=form.get('input1').value!='optional' &&
           !form.get('input2').value?{required:true}:null;
      form.get('input2').setErrors(error); //<--see the setErrors
      return error;
    }
  }

请参见stackblitz

答案 1 :(得分:1)

对于跨字段验证,您可以使用required的{​​{1}}验证。

您只需要像这样在formControl中提及@rxweb/reactive-form-validation

conditionalExpression

像这样在您的app.component.ts中设置错误消息

input2:['', RxwebValidators.required({conditionalExpression:'x => x.input1 == "mandatory"' })]

这是您完整的组件代码:

ngOnInit(){
    ReactiveFormConfig.set({"validationMessage":{"required":"This field is required"}});
  }

这是您的完整HTML代码:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder } from "@angular/forms"
import { RxwebValidators } from '@rxweb/reactive-form-validators';

@Component({
    selector: 'app-required-conditionalExpression-validator',
    templateUrl: './required-conditional-expression.component.html'
})
export class RequiredConditionalExpressionValidatorComponent implements OnInit {
    userFormGroup: FormGroup

    constructor(
        private formBuilder: FormBuilder )
    { }

    ngOnInit() {
        this.userFormGroup = this.formBuilder.group({
            input1:[''], 
            input2:['', RxwebValidators.required({conditionalExpression:'x => x.input1 == "mandatory"' })], 
        });
    }
}

这里是Working Example