Angular 4/5中临时禁用全表单验证(不禁用表单)的方法
Hey there! 很遗憾的是,Angular 4/5本身并没有提供像this.form.disableValidators()这种开箱即用的便捷方法来一次性禁用整个表单的验证。不过别担心,我们可以自己实现相对简洁的方案,不用手动挨个移除验证器那么麻烦。
下面给你几个实用的解决思路:
方案1:封装通用工具函数批量控制验证器
我们可以写一对工具函数,用来保存表单控件的原始验证器,然后批量移除或恢复它们,完美适配你的表单场景:
import { FormGroup, AbstractControl, ValidatorFn } from '@angular/forms'; // 用Map保存每个控件的原始验证器,避免丢失 const originalValidatorsStore = new Map<AbstractControl, { validators: ValidatorFn[] | null, asyncValidators: ValidatorFn[] | null }>(); // 禁用整个表单的验证(包括同步+异步验证器) export function disableFormValidators(form: FormGroup) { // 处理表单级别的验证器 originalValidatorsStore.set(form, { validators: form.validator ? [form.validator] : null, asyncValidators: form.asyncValidator ? [form.asyncValidator] : null }); form.clearValidators(); form.clearAsyncValidators(); // 处理每个表单控件的验证器 Object.values(form.controls).forEach(control => { originalValidatorsStore.set(control, { validators: control.validator ? [control.validator] : null, asyncValidators: control.asyncValidator ? [control.asyncValidator] : null }); control.clearValidators(); control.clearAsyncValidators(); // 更新控件状态,不触发额外事件 control.updateValueAndValidity({ emitEvent: false, onlySelf: true }); }); form.updateValueAndValidity({ emitEvent: false, onlySelf: true }); } // 恢复整个表单的验证 export function enableFormValidators(form: FormGroup) { // 恢复表单级别的验证器 const formValidators = originalValidatorsStore.get(form); if (formValidators) { form.setValidators(formValidators.validators); form.setAsyncValidators(formValidators.asyncValidators); } // 恢复每个控件的验证器 Object.values(form.controls).forEach(control => { const controlValidators = originalValidatorsStore.get(control); if (controlValidators) { control.setValidators(controlValidators.validators); control.setAsyncValidators(controlValidators.asyncValidators); control.updateValueAndValidity({ emitEvent: false, onlySelf: true }); } }); form.updateValueAndValidity({ emitEvent: false, onlySelf: true }); }
针对你给出的表单代码,使用起来超简单:
// 临时禁用验证 disableFormValidators(this.form); // 恢复验证功能 enableFormValidators(this.form);
这里的emitEvent: false和onlySelf: true是为了避免触发不必要的表单值变更事件,如果你需要触发事件,可以调整这些参数。
方案2:自定义指令(适合多表单复用场景)
如果你的项目里多个表单都需要这个功能,写一个自定义指令会更优雅,通过布尔值来开关验证:
import { Directive, Input, OnChanges, SimpleChanges } from '@angular/core'; import { FormGroup, AbstractControl, ValidatorFn } from '@angular/forms'; @Directive({ selector: '[appToggleFormValidation]' }) export class ToggleFormValidationDirective implements OnChanges { @Input() appToggleFormValidation = false; private originalValidatorsStore = new Map<AbstractControl, { validators: ValidatorFn[] | null, asyncValidators: ValidatorFn[] | null }>(); constructor(private form: FormGroup) {} ngOnChanges(changes: SimpleChanges) { if (changes['appToggleFormValidation']) { this.toggleValidation(this.appToggleFormValidation); } } private toggleValidation(disable: boolean) { if (disable) { // 保存所有验证器并清除 this.saveAllValidators(); this.clearAllValidators(); } else { // 恢复所有验证器 this.restoreAllValidators(); } } private saveAllValidators() { // 保存表单级别验证器 this.originalValidatorsStore.set(this.form, { validators: this.form.validator ? [this.form.validator] : null, asyncValidators: this.form.asyncValidator ? [this.form.asyncValidator] : null }); // 保存控件级别验证器 Object.values(this.form.controls).forEach(control => { this.originalValidatorsStore.set(control, { validators: control.validator ? [control.validator] : null, asyncValidators: control.asyncValidator ? [control.asyncValidator] : null }); }); } private clearAllValidators() { this.form.clearValidators(); this.form.clearAsyncValidators(); Object.values(this.form.controls).forEach(control => { control.clearValidators(); control.clearAsyncValidators(); control.updateValueAndValidity({ emitEvent: false, onlySelf: true }); }); this.form.updateValueAndValidity({ emitEvent: false, onlySelf: true }); } private restoreAllValidators() { // 恢复表单级别验证器 const formValidators = this.originalValidatorsStore.get(this.form); if (formValidators) { this.form.setValidators(formValidators.validators); this.form.setAsyncValidators(formValidators.asyncValidators); } // 恢复控件级别验证器 Object.values(this.form.controls).forEach(control => { const controlValidators = this.originalValidatorsStore.get(control); if (controlValidators) { control.setValidators(controlValidators.validators); control.setAsyncValidators(controlValidators.asyncValidators); control.updateValueAndValidity({ emitEvent: false, onlySelf: true }); } }); this.form.updateValueAndValidity({ emitEvent: false, onlySelf: true }); } }
然后在模板里直接用:
<form [formGroup]="form" [appToggleFormValidation]="isValidationDisabled"> <input formControlName="email" type="email" placeholder="Email"> <input formControlName="password" type="password" placeholder="Password"> </form>
在组件里只需要控制isValidationDisabled这个布尔变量,就能轻松开关整个表单的验证了。
小提示
如果你的表单里有嵌套的FormGroup或FormArray,上面的工具函数和指令可以稍微扩展一下,递归处理嵌套的控件,这样就能覆盖更复杂的表单结构啦。
内容的提问来源于stack exchange,提问作者ovg
相关产品推荐
相关产品推荐

