Angular响应式表单hasValidator对自定义验证器返回false问题
为什么Angular的
hasValidator检测自定义验证器返回false?如何解决? 问题原因
Angular的hasValidator方法是通过函数引用相等性来判断验证器是否存在的:
- 内置验证器如
Validators.required是一个固定的全局函数实例,无论调用多少次都是同一个引用,因此检测时返回true。 - 你的
trimValidator是一个工厂函数,每次调用trimValidator(10, 3000)都会生成并返回一个全新的ValidatorFn函数实例,两次调用的函数引用完全不同,所以hasValidator返回false。
另外注意原验证器代码存在两个小问题:
- 长度超过最大值时,错误键错误地返回了
minlength,应该改为maxlength; - 验证通过时缺少
return null的逻辑,Angular要求验证器必须在通过时返回null。
解决方案
方案一:缓存验证器实例(组件内复用)
在组件中提前生成并保存验证器的引用,表单赋值和检测时都使用这个引用:
import { Component } from '@angular/core'; import { FormBuilder, Validators } from '@angular/forms'; import { trimValidator } from './trim.validator'; @Component({ selector: 'app-example', templateUrl: './example.component.html' }) export class ExampleComponent { // 提前生成并缓存验证器实例 private readonly descriptionTrimValidator = trimValidator(10, 3000); myform = this.fb.group({ name: ['', [Validators.required]], // 使用缓存的验证器实例 description: ['', [this.descriptionTrimValidator]] }); checkValidator() { // 用同一个引用检测 const hasValidator = this.myform.get('description')?.hasValidator(this.descriptionTrimValidator); console.log(hasValidator); // 输出true } constructor(private fb: FormBuilder) {} }
方案二:改造工厂函数,全局缓存相同参数的验证器
如果需要在多个组件中复用相同参数的trimValidator,可以改造工厂函数,让相同参数的调用返回同一个函数实例:
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; // 用Map缓存参数对应的验证器实例 const validatorCache = new Map<string, ValidatorFn>(); export function trimValidator(minlength: number, maxlength: number): ValidatorFn { const cacheKey = `${minlength}-${maxlength}`; // 缓存存在则直接返回 if (validatorCache.has(cacheKey)) { return validatorCache.get(cacheKey)!; } const validator: ValidatorFn = ({ value }: AbstractControl): ValidationErrors | null => { const trimValue = value?.trim() || ''; if (trimValue.length < minlength) { return { minlength: true }; } else if (trimValue.length > maxlength) { return { maxlength: true }; // 修复错误键 } return null; // 补充验证通过的返回逻辑 }; validatorCache.set(cacheKey, validator); return validator; }
改造后,多次调用trimValidator(10, 3000)都会返回同一个函数引用,此时hasValidator就能正确检测到验证器存在。
内容的提问来源于stack exchange,提问作者Mithun J
相关产品推荐
相关产品推荐

