Angular自定义校验指令报错:TypeError: validator is not a function
问题分析与修复方案
核心错误原因
报错validator is not a function是因为你传递给setValidators的是返回验证函数的方法引用,而非实际的ValidatorFn实例。比如this.validate1是方法本身,不是它返回的验证函数,必须调用this.validate1()才能得到可用的验证器。
具体修复步骤
1. 修正基础语法错误
- 拼写错误:
NG_VAILDATORS改为NG_VALIDATORS(注意字母L) - 指令选择器:
selector属性值应为字符串'[appdirective1]',而非数组 - Input语法:
@Input后必须加括号,正确写法如@Input() varName1 = "";
2. 传递正确的验证函数实例
将所有setValidators中的方法引用改为调用方法,示例:
// 错误写法 control.control.setValidators(this.validate1); // 正确写法 control.control.setValidators(this.validate1());
3. 避免验证器被覆盖
setValidators会替换控件上所有已有的验证器,若需保留原有验证器(如表单自带的必填、长度验证),应合并现有验证器数组:
const control = this._injector.get(NgControl); const existingValidators = control.control.validator ? [control.control.validator] : []; const newValidators = [...existingValidators]; // 添加基础验证器 newValidators.push(this.validate1()); // 根据输入参数添加对应验证器 if (this.varName1) { newValidators.push(this.validate2()); } if (this.varName2) { newValidators.push(this.validate3()); } control.control.setValidators(newValidators);
4. 确保this指向正确
validate2和validate3中调用this.callBack1()时,需保证this指向指令实例。由于验证函数用箭头函数定义,已保留外层this,但组件传递的callBack1、callBack2需正确绑定(比如在组件中用箭头函数定义,或在构造函数中绑定)。
5. 完善ngOnChanges逻辑
当输入参数变化时(如varName1从有值变为空),需移除对应验证器。可维护当前激活的验证器列表,根据输入状态更新:
ngOnChanges(changes: SimpleChanges) { const control = this._injector.get(NgControl); const existingValidators = control.control.validator ? [control.control.validator] : []; const newValidators = [...existingValidators, this.validate1()]; // 处理varName1的变化 if (changes['varName1']) { if (this.varName1) { newValidators.push(this.validate2()); } } // 处理varName2的变化 if (changes['varName2']) { if (this.varName2) { newValidators.push(this.validate3()); } } control.control.setValidators(newValidators); control.control.updateValueAndValidity({ emitEvent: false }); }
6. 更规范的实现方式(推荐)
既然已在指令中提供NG_VALIDATORS,更符合Angular规范的做法是实现Validator接口,通过validate方法返回组合后的验证器,而非手动操作NgControl:
import { Directive, Input, OnChanges, SimpleChanges } from '@angular/core'; import { AbstractControl, Validator, ValidatorFn, ValidationErrors, NG_VALIDATORS, forwardRef, composeValidators } from '@angular/forms'; @Directive({ selector: '[appdirective1]', providers: [ { provide: NG_VALIDATORS, useExisting: forwardRef(() => DirectiveName), multi: true // 多个验证器时必须设置multi为true } ] }) export class DirectiveName implements Validator, OnChanges { @Input() varName1 = ""; @Input() varName2 = ""; @Input() callBack1: () => any; @Input() callBack2: () => any; private validators: ValidatorFn[] = [this.validate1()]; private onChange?: () => void; validate(control: AbstractControl): ValidationErrors | null { return composeValidators(this.validators)?.(control); } registerOnValidatorChange(fn: () => void): void { this.onChange = fn; } ngOnChanges(): void { this.validators = [this.validate1()]; if (this.varName1) { this.validators.push(this.validate2()); } if (this.varName2) { this.validators.push(this.validate3()); } this.onChange?.(); } private validate1(): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { // 你的验证逻辑 return null; }; } private validate2(): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { const obj1 = this.callBack1(); // 你的验证逻辑 return null; }; } private validate3(): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { const obj1 = this.callBack2(); // 你的验证逻辑 return null; }; } }
修复后注意事项
- 组件中传递的
method1、method2需确保绑定正确,比如用箭头函数定义:method1 = () => { // 你的回调逻辑 return someValue; }; - 调用
updateValueAndValidity时可添加{ emitEvent: false }参数,避免不必要的表单事件循环。
内容的提问来源于stack exchange,提问作者Angular Guru
相关产品推荐
相关产品推荐

