角度-动态添加/删除验证器

我有一个 FormGroup定义如下:

this.businessFormGroup: this.fb.group({
'businessType': ['', Validators.required],
'description': ['', Validators.compose([Validators.required, Validators.maxLength(200)])],
'income': ['']
})

现在,当 businessTypeOther时,我想从 description中删除 Validators.required验证器。如果 businessType不是 Other,我想加回 Validators.required

我使用下面的代码来动态添加/删除 Validators.required

if(this.businessFormGroup.get('businessType').value !== 'Other'){
this.businessFormGroup.get('description').validator = <any>Validators.compose([Validators.required]);
} else {
this.businessFormGroup.get('description').clearValidators();
}


this.businessFormGroup.get('description').updateValueAndValidity();

我的问题是,在添加/删除 required验证程序时,如何保留现有的验证程序。

106498 次浏览

如果你使用角度12.2或更高,你可以使用 AbstractControl方法 addValidatorsremoveValidators,和 hasValidator根据文件:

if(this.businessFormGroup.get('businessType').value !== 'Other'){
this.businessFormGroup.get('description').addValidators(Validators.required);
} else {
this.businessFormGroup.get('description').clearValidators();
}

对于较老的版本,角形表单有一个内置的函数 SetValidators (),它支持对验证器进行编程分配。但是,这将覆盖您的验证程序。

举个例子,你可以这样做:

if(this.businessFormGroup.get('businessType').value !== 'Other'){
this.businessFormGroup.controls['description'].setValidators([Validators.required, Validators.maxLength(200)]);
} else {
this.businessFormGroup.controls['description'].setValidators([Validators.maxLength(200)]);
}
this.businessFormGroup.controls['description'].updateValueAndValidity();

记住 通过使用此方法,您将覆盖现有的验证程序是很重要的,因此您需要包含所有您需要/想要的验证器来重置控件。

幼稚的方法是在条件变量发生变化时设置控件的验证器。但是我们实际上可以通过使用间接 + 函数式编程做得更好。

考虑 descriptionIsRequired getter 的存在,它充当一个 boolan 标志。

想法:

  • 创建一个自定义验证器函数,该函数以 descriptionIsRequired为参数,并根据它验证所需的 + maxLlength 或 maxLlength 控件。
  • 将自定义验证器绑定到描述控件,以便在评估控件的有效性时,应考虑 descriptionIsRequired的最新值。

第一点很容易实现:

function descriptionValidator(required: boolean): ValidatorFn {
return (formControl: FormControl): ValidationErrors => {
if (required) {
return Validators.compose([Validators.required, Validators.maxLength(200)])(formControl);
} else {
return Validators.maxLength(200)(formControl);
}
}
}

注意,这是一个自封装的函数。

第二点比较棘手,但最后看起来是这样的:

export class FooComponent {
constructor(){
this.form = fb.group({
description: ['initial name', this.validator()]
});
}


private get descriptionIsRequired(): boolean {
...
}


private validator(): ValidatorFn {
return (c: FormControl): ValidationErrors => descriptionValidator(this.descriptionIsRequired)(c);
}
}

对目前情况的一个小小的解释是:

  • validator方法返回一个函数
  • validator返回的函数可以被视为 工厂法: 每当它被调用时,都会返回一个新函数,更具体地说,是使用最新的 descriptionIsRequired值的 descriptionValidator的一个新实例。

以下 Stackblitz中的现场演示

也许这会有所帮助:

向现有 AbstractControl的验证器集添加 Validators.need:

if (c.validator !== null) {
c.setValidators([c.validator, Validators.required])
} else {
c.setValidators([Validators.required])
}

这个对我有用

onAddValidationClick(){
this.formGroup.controls["firstName"].setValidators(Validators.required);
this.formGroup.controls["firstName"].updateValueAndValidity();
}


onRemoveValidationClick(){
this.formGroup.controls["firstName"].clearValidators();
this.formGroup.controls["firstName"].updateValueAndValidity();
}

任何仍在寻找答案的人,都可以这样做,在 ngOnInit ()或任何您喜欢的地方处理它。

   const validators = formGroup.validator; /* or control.validator */


const newValidator = CustomValidator.checkUserNameValidity();


/* Add to existing validator */


if(validator) {
formGroup.setValidators([validators, newValidator])
} else {. /* if no validators added already */
formGroup.setValidators([newValidator]);
}


也可以使用相同的方法处理 syncValidator。

如果您多次更改“验证器必需”(例如,使用复选框) ,您应该添加以下内容:

this.formGroup.controls["firstName"].setErrors(null);

所以:

  onAddValidationClick(){
this.formGroup.controls["firstName"].setValidators(Validators.required);
this.formGroup.controls["firstName"].updateValueAndValidity();
}


onRemoveValidationClick(){
this.formGroup.controls["firstName"].setErrors(null);
this.formGroup.controls["firstName"].clearValidators();
this.formGroup.controls["firstName"].updateValueAndValidity();
}

如果您多次更改“验证器必需”(例如,使用复选框) ,您应该添加以下内容: 非常重要的领域! FormGroup.control [“ firstName”] . setError (null) ;

我有一些表单,根据上下文需要一些值,但在其他表单中可以省略它们。在我的例子中,仅仅调用‘ mainform.updateValueAndVality ()’是不够的。在动态设置所需验证时,我必须显式地更新该字段:

formField.setValidators([RxwebValidators.required()]);
formField.updateValueAndValidity({onlySelf: true});

关键是{ onlySelf: true }