You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 20:24:52