Angular自定义验证器绑定全局变量到ValidationErrors报错如何解决
问题原因
报错核心是this上下文丢失:Angular执行表单校验器时,会在表单模块的独立上下文中调用校验方法,默认不会绑定组件实例作为this,所以校验方法内的this是undefined,自然无法读取foundEmail属性。
解决方法
以下是3种常用可行方案:
- 方案1:用箭头函数定义校验方法(最便捷,推荐)
箭头函数会绑定定义时的词法上下文,不会被调用方修改this指向,直接调整原有方法的定义方式即可:
isUniqueEmail = (control: FormControl): ValidationErrors | null => { if (control.value != null) { console.log(control.value) if(control.value == this.foundEmail){ console.log("found one"); return {isUniqueEmail: true} } } return null; }
后续正常把this.isUniqueEmail加入表单校验规则数组即可,无需额外处理。
- 方案2:注册校验器时手动绑定
this
如果不想修改原有方法的写法,可以在给FormControl添加校验规则时,用bind方法手动绑定组件实例作为上下文:
// 表单初始化部分示例 this.emailControl = new FormControl('', [ Validators.required, Validators.email, this.isUniqueEmail.bind(this) // 绑定当前组件实例作为校验方法的this ]);
- 方案3:用闭包工厂函数传递参数(无this依赖,可复用)
如果校验逻辑需要在多个组件复用,可以把校验器封装为工厂函数,直接接收已存在的邮箱作为参数,不需要依赖组件的this:
// 可单独抽离到公共校验工具文件,也可定义在组件内 function isUniqueEmailValidator(existEmail: string): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { if (control.value == null) return null; return control.value === existEmail ? {isUniqueEmail: true} : null; } } // 注册校验器时传入当前组件的foundEmail this.emailControl = new FormControl('', [ Validators.required, Validators.email, isUniqueEmailValidator(this.foundEmail) ]);
注意:如果
foundEmail是异步获取的(比如从后端接口查询后赋值),使用该方案需要在foundEmail赋值完成后,手动调用emailControl.updateValueAndValidity()重新触发校验,否则会用初始值做校验。
内容的提问来源于stack exchange,提问作者mester lio
相关产品推荐
相关产品推荐

