Angular 4 有条件地删除所需的验证器
Posted
技术标签:
【中文标题】Angular 4 有条件地删除所需的验证器【英文标题】:Angular 4 remove required validator conditionally 【发布时间】:2018-03-11 07:33:26 【问题描述】:在 Angular 4 应用程序中,我有一个这样的表单模型:
this.form = this._fb.group(
title: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(50)]],
description: ['', [Validators.required, Validators.minLength(3)]]
);
现在我想要的是从控件验证器数组中动态删除所需的验证器。像这样的:
saveDraft()
this.form.controls['title'].removeValidator('required'); //Just a fake implementation for demonstration
这个问题不是上述问题的重复。我的情况不同,我只是想在不知情的情况下删除所需的验证器。
【问题讨论】:
Angular 2 conditional Validators.required?的可能重复 【参考方案1】:你可以使用:AbstractControl.removeValidators(validator: ValidatorFn)
不确定在 Angular 4 中是否可行,但肯定在 Angular 12 及更高版本中。
但是,它需要对exact same function 的引用。 仅仅给它 Validators.required 是行不通的。您需要为它创建一个唯一的引用:
requiredValidator = Validators.required;
this.form = this._fb.group(
title: ['', [this.requiredValidator, Validators.minLength(3), Validators.maxLength(50)]],
description: ['', [this.requiredValidator, Validators.minLength(3)]]
);
saveDraft()
this.title.removeValidator(this.requiredValidator);
get title(): AbstractControl
return this.form.get('title');
【讨论】:
【参考方案2】:我们可以使用setValidators
来移除验证。
setValidators(newValidator: ValidatorFn | ValidatorFn[]): void
setValidators() - setValidators 以编程方式添加同步验证器。此方法将删除所有之前添加的同步或异步验证器。
this.form.get('title').setValidators(null);
this.form.get('title').setErrors(null);
【讨论】:
它对我有用。当项的值为空时,它使表单有效。【参考方案3】:this.fromName.get("formControlName").setValidators([Validators.required]);//setting validation
this.fromName.get("formControlName").setErrors('required':true);//error message
this.fromName.updateValueAndValidity();//update validation
this.fromName.get("formControlName").clearValidators([Validators.required]);//clear validation
this.fromName.get("formControlName").setErrors(null);//updating error message
this.fromName.updateValueAndValidity();//update validation
【讨论】:
虽然此代码可能会为问题提供解决方案,但最好添加有关其工作原理/方式的上下文。这可以帮助未来的用户学习并将这些知识应用到他们自己的代码中。在解释代码时,您也可能会以赞成票的形式从用户那里获得积极的反馈。 clearValidators() 不接受参数,并清除所有验证器。见angular.io/api/forms/AbstractControl#clearValidatorsclearValidators()
上没有参数。为什么人们投票给这个错误的信息..!!!【参考方案4】:
您可以使用它来清除响应式表单中的验证
this.form.controls['title'].clearValidators(); this.form.controls['title'].updateValueAndValidity();
您可以使用它以反应形式添加验证
this.form.controls['title'].setValidators([Validators.required]); this.form.controls['title'].updateValueAndValidity();
【讨论】:
【参考方案5】:使用空数组删除所有现有的验证器。
this.frmFeasibility.controls['pop_name'].setValidators([]);
this.frmFeasibility.controls['pop_name'].updateValueAndValidity();
【讨论】:
【参考方案6】:添加验证器:
this.form = this._fb.group(
title: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(50)]],
description: ['', [Validators.required, Validators.minLength(3)]]
);
或
this.form.get('title').setValidators([Validators.required,Validators.minLength(3),
Validators.maxLength(50)]);
要仅删除“必需”验证器,您可以重置验证器。
saveDraft()
this.form.get('title').setValidators([Validators.minLength(3), Validators.maxLength(50)]);
this.form.get('title').updateValueAndValidity();
updateValueAndValidity 确定控件如何传播更改并在值和验证器更改时发出事件
【讨论】:
【参考方案7】:我不喜欢清除和设置验证器,因为我必须重复所有静态验证器(模式、最小值、最大值等)才能拥有一个动态的“必需”验证器。
我使用条件验证器:
export function conditionalValidator(condFn: (control: AbstractControl) => boolean,
validators: ValidatorFn | ValidatorFn[]): ValidatorFn
return (control) =>
if (!condFn(control))
return null;
if (!Array.isArray(validators))
return validators(control);
return validators.map(v => v(control)).reduce((errors, result) =>
result === null ? errors :
(Object.assign(errors || , result))
);
;
然后我可以将静态验证器与动态“必需”条件混合:
this.fb.group(name: ['', [Validators.minLength(4),
conditionalValidator(this.isClientProj, Validators.required)]]
其中isClientProj()
是条件函数(闭包)
【讨论】:
我认为这里需要注意的是,需要做一些事情来确保条件值的变化会触发重新验证。我认为复选框的更改不会触发其他表单字段的验证。 对,这就是我目前正在尝试解决的问题。如果您处于无效状态并且验证器条件更改为 false,则表单仍然无效,除非您手动启动不太理想的验证周期。 Validator 接口确实定义了一个 changed 事件钩子,据我所知,它是 Angular 钩子再次触发验证的原因,所以我要尝试一下。【参考方案8】:我在将条目保存为草稿时遇到了同样的问题,并准备了以下解决方案:
@Component(
// ...
)
export class FormComponent
form: FormGroup;
constructor(private fb: FormBuilder)
this.form = this.fb.group(
name: ['', Validators.required, Validators.maxLength(20)],
description: ['', Validators.required, Validators.maxLength(200)],
address: this.fb.group(
line1: ['', Validators.required, Validators.maxLength(100)],
line2: ['', Validators.maxLength(100)]
)
);
validateDraft(formElement: FormGroup | FormArray | FormControl): boolean
let result = true;
Object.keys(formElement.controls).forEach(field =>
const control = formElement.get(field);
if(control instanceof FormControl)
control.markAsTouched( onlySelf: true );
if(control.errors && control.errors['required'])
control.markAsUntouched( onlySelf: true );
else if(control.invalid)
result = false;
else if (control instanceof FormArray)
if (!this.validateDraft(control))
result = false;
else if (control instanceof FormGroup)
if (!this.validateDraft(control))
result = false;
);
saveDraft()
if(this.validateDraft(this.form))
//save draft - ignore required errors
save()
if(this.form.valid)
//save
【讨论】:
这对我来说是最好的解决方案【参考方案9】:不幸的是,Angular 目前还没有 removeValidator 功能。您所能做的就是重新设置验证器,而不是要删除的验证器,因此您需要知道要保留哪些验证器,而不是要删除的验证器。所以这个:
this.form.get('title').setValidators([Validators.minLength(3), Validators.maxLength(50)]);
是最接近删除功能的方法。您也无法访问表单控件上的当前验证器来尝试编写自己的删除函数。您能做的最好的事情就是编写自己的表单控件验证管理器类,该类可以跟踪给定控件上的验证器并为您管理它们。
【讨论】:
我在这里是因为我设置了 min/maxlength 的控件在空字段上仍然出现required
错误。【参考方案10】:
如果你想添加验证,试试这个。
saveDraft()
this.form.get('title').setValidators([Validators.required, Validators.minLength(3)]);
this.form.get('title').updateValueAndValidity();
如果你想删除验证器,试试这个。
saveDraft()
this.form.get('title').clearValidators();
this.form.get('title').updateValueAndValidity();
【讨论】:
这对我不起作用。在我的情况下,我有更改事件的下拉菜单,我正在调用一个函数来设置验证器,如上所述。任何可能有问题的建议。 @Zaker 请使用您的代码发布一个新问题,并链接到该问题。 对于遇到此问题的其他人,我必须执行 this.form.get('title').setValidators(null); this.form.get('title').setErrors(null) 以确保 this.form.valid = true @CalebSwank 感谢您添加此内容。setErrors(null)
和 setValidators(null);
工作得很好。 :-)
但是当您再次添加所需的验证器时删除错误后,您需要添加错误:(.以上是关于Angular 4 有条件地删除所需的验证器的主要内容,如果未能解决你的问题,请参考以下文章