Angular响应式表单自定义组验证器遇TS1068错误及验证失效,如何解决?
搞定Angular密码匹配验证器的那些坑
我来帮你理清这个表单验证的问题~首先得先澄清一个误区:用独立function写自定义验证器完全合法,Angular官方文档里也有不少这样的示例,所以你之前搜到的“不应使用function关键字”大概率是个误解,或者是针对类内部方法声明的场景而言。
先说说你原来的代码为什么能工作
你写的checkPassword是一个独立函数,不属于组件类,所以直接把它作为validator参数传递时,不需要考虑this的指向问题——它本身就不需要访问组件的任何属性或方法,只需要接收表单组参数做判断就行,这也是为什么你重新保存(没改代码)就能编译成功,因为它本身就是正确的写法。
为什么移除function关键字后验证失效?
如果你把checkPassword改成了组件类的成员方法(比如去掉function关键字,写成类里的方法),直接传this.checkPassword会出问题,因为当Angular调用这个验证器时,this的指向会变成表单组实例,而不是你的组件实例。不过好在这个验证器其实不需要组件的this,所以我们可以用下面几种方式解决:
方案1:用箭头函数定义类方法
箭头函数会自动绑定组件的this,完美避免指向问题:
import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms'; export class YourComponent { // 用箭头函数定义验证器方法 checkPassword = (group: FormGroup): { [s: string]: boolean } | null => { if (group.value.password !== group.value.confirmPassword) { return { 'passwordMismatch': true }; } return null; }; constructor(private formBuilder: FormBuilder) {} ngOnInit() { this.form = this.formBuilder.group({ 'emailAddress': new FormControl(null, [ Validators.required, Validators.email, this.checkEmailAddress.bind(this) ]), 'username': new FormControl(null, [ Validators.required, Validators.maxLength(16), this.checkUsername.bind(this) ]), 'passGroup': this.formBuilder.group({ 'password': new FormControl(null, [ Validators.required ]), 'confirmPassword': new FormControl(null, [ Validators.required ]) }, { validator: this.checkPassword }) // 直接传this.checkPassword即可 }); } // 你的其他自定义验证器 checkEmailAddress(control: FormControl) { /* ... */ } checkUsername(control: FormControl) { /* ... */ } }
方案2:传递时绑定this
如果习惯用普通类方法,在传递验证器时用bind(this)固定指向:
export class YourComponent { constructor(private formBuilder: FormBuilder) {} ngOnInit() { this.form = this.formBuilder.group({ // ...其他控件 'passGroup': this.formBuilder.group({ 'password': new FormControl(null, [ Validators.required ]), 'confirmPassword': new FormControl(null, [ Validators.required ]) }, { validator: this.checkPassword.bind(this) }) // 绑定组件的this }); } checkPassword(group: FormGroup): { [s: string]: boolean } | null { if (group.value.password !== group.value.confirmPassword) { return { 'passwordMismatch': true }; } return null; } // ...其他方法 }
方案3:定义为静态方法
静态方法不需要实例的this,适合这种无上下文依赖的验证器:
export class YourComponent { constructor(private formBuilder: FormBuilder) {} ngOnInit() { this.form = this.formBuilder.group({ // ...其他控件 'passGroup': this.formBuilder.group({ 'password': new FormControl(null, [ Validators.required ]), 'confirmPassword': new FormControl(null, [ Validators.required ]) }, { validator: YourComponent.checkPassword }) // 直接用类名访问静态方法 }); } // 静态验证器方法 static checkPassword(group: FormGroup): { [s: string]: boolean } | null { if (group.value.password !== group.value.confirmPassword) { return { 'passwordMismatch': true }; } return null; } // ...其他方法 }
关于你尝试this.checkPassword和bind(this)报错的问题
大概率是类型或依赖注入的问题:
- 确保你已经正确导入了
FormGroup等表单类 - 组件构造函数里一定要注入
FormBuilder:constructor(private formBuilder: FormBuilder) {} - 检查验证器方法的返回值类型,Angular要求验证器返回
{ [key: string]: boolean } | null,不要漏了| null
内容的提问来源于stack exchange,提问作者Jonathan Lightbringer
相关产品推荐
相关产品推荐

