Angular - 动态 add/remove 验证者
Angular - Dynamically add/remove validators
我有一个 FormGroup
定义如下:
this.businessFormGroup: this.fb.group({
'businessType': ['', Validators.required],
'description': ['', Validators.compose([Validators.required, Validators.maxLength(200)])],
'income': ['']
})
现在,当 businessType
为 Other
时,我想从 description
中删除 Validators.required
验证器。如果 businessType
不是 Other
,我想加回 Validators.required
。
我正在使用下面的代码来动态 add/remove Validators.required
。但是,它会清除现有的 Validators.maxLength
验证器。
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();
我的问题是,当 adding/removing 验证器为 required
时,如何保留现有验证器。
如果您使用 Angular 12.2 或更高版本,您可以使用 AbstractControl
方法 addValidators
、removeValidators
和 hasValidator
、as per the docs:
if(this.businessFormGroup.get('businessType').value !== 'Other'){
this.businessFormGroup.get('description').addValidators(Validators.required);
} else {
this.businessFormGroup.get('description').clearValidators();
}
对于旧版本,Angular 表单有一个内置函数 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();
请务必牢记,通过使用此方法,您将覆盖现有的验证器,因此您需要包括所有 need/want 的验证器控制你正在重置。
天真的方法是在条件变量发生变化时设置控件的验证器。但我们实际上可以通过使用一些间接 + 函数式编程来做得更好。
考虑作为布尔标志的 descriptionIsRequired
getter 的存在。
想法:
- 创建一个将
descriptionIsRequired
作为参数的自定义验证器函数,并根据它根据 required + maxLength 或 maxLength 验证控件。
- 以这种方式将自定义验证器绑定到描述控件,以便在评估控件的有效性时,应考虑
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
方法returns函数
validator
返回的函数可以被认为是一个 工厂方法:每当它被调用时,returns 一个新函数,更具体地说,一个新实例我们的 descriptionValidator
使用最新的 descriptionIsRequired
值。
现场演示如下stackblitz
也许这有帮助:
将 Validators.required 添加到现有 AbstractControl
的验证器集:
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]);
}
对 asyncValidator 也进行同样的操作。
如果您多次更改 "validator required"(例如,使用复选框),您应该添加:
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();
}
如果您多次更改 "validator required"(例如,使用复选框),您应该添加:
非常重要的领域!
this.formGroup.controls["firstName"].setErrors(null);
我有一些表格,根据上下文需要一些值,但在其他表格中可以省略。在我的例子中,调用 'mainform.updateValueAndValidity()' 是不够的。当我动态设置需要验证时,我必须显式更新该字段:
formField.setValidators([RxwebValidators.required()]);
formField.updateValueAndValidity({onlySelf: true});
密钥是 {onlySelf: true}
我有一个 FormGroup
定义如下:
this.businessFormGroup: this.fb.group({
'businessType': ['', Validators.required],
'description': ['', Validators.compose([Validators.required, Validators.maxLength(200)])],
'income': ['']
})
现在,当 businessType
为 Other
时,我想从 description
中删除 Validators.required
验证器。如果 businessType
不是 Other
,我想加回 Validators.required
。
我正在使用下面的代码来动态 add/remove Validators.required
。但是,它会清除现有的 Validators.maxLength
验证器。
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();
我的问题是,当 adding/removing 验证器为 required
时,如何保留现有验证器。
如果您使用 Angular 12.2 或更高版本,您可以使用 AbstractControl
方法 addValidators
、removeValidators
和 hasValidator
、as per the docs:
if(this.businessFormGroup.get('businessType').value !== 'Other'){
this.businessFormGroup.get('description').addValidators(Validators.required);
} else {
this.businessFormGroup.get('description').clearValidators();
}
对于旧版本,Angular 表单有一个内置函数 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();
请务必牢记,通过使用此方法,您将覆盖现有的验证器,因此您需要包括所有 need/want 的验证器控制你正在重置。
天真的方法是在条件变量发生变化时设置控件的验证器。但我们实际上可以通过使用一些间接 + 函数式编程来做得更好。
考虑作为布尔标志的 descriptionIsRequired
getter 的存在。
想法:
- 创建一个将
descriptionIsRequired
作为参数的自定义验证器函数,并根据它根据 required + maxLength 或 maxLength 验证控件。 - 以这种方式将自定义验证器绑定到描述控件,以便在评估控件的有效性时,应考虑
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
方法returns函数validator
返回的函数可以被认为是一个 工厂方法:每当它被调用时,returns 一个新函数,更具体地说,一个新实例我们的descriptionValidator
使用最新的descriptionIsRequired
值。
现场演示如下stackblitz
也许这有帮助:
将 Validators.required 添加到现有 AbstractControl
的验证器集:
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]);
}
对 asyncValidator 也进行同样的操作。
如果您多次更改 "validator required"(例如,使用复选框),您应该添加:
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();
}
如果您多次更改 "validator required"(例如,使用复选框),您应该添加: 非常重要的领域! this.formGroup.controls["firstName"].setErrors(null);
我有一些表格,根据上下文需要一些值,但在其他表格中可以省略。在我的例子中,调用 'mainform.updateValueAndValidity()' 是不够的。当我动态设置需要验证时,我必须显式更新该字段:
formField.setValidators([RxwebValidators.required()]);
formField.updateValueAndValidity({onlySelf: true});
密钥是 {onlySelf: true}