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#clearValidators clearValidators() 上没有参数。为什么人们投票给这个错误的信息..!!!【参考方案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 有条件地删除所需的验证器的主要内容,如果未能解决你的问题,请参考以下文章

使用 asp.net core 删除所需的验证

Mongoose 所需的验证器失败值未定义

Mongoose 所需的验证器失败值未定义

隐藏 WooCommerce 结帐字段后删除所需的验证

仅在第一个组件通过验证时有条件地更新第二个组件

使用javascript提交验证所需的属性