Angular 5自定义验证指令如何使用多参数?
哈哈,这个问题问到点子上了!完全可以用string[]或者Object类型的@Input替代原单一字符串的限制,还能让验证逻辑更灵活。我给你分情况拆解清楚:
一、改用
string[]类型的@Input(支持多个禁用名称) 这是最直接的多参数方案,把原来接收单个字符串的@Input改成数组类型,然后在验证器里检查输入值是否在禁用列表中即可。
指令代码调整:
import { Directive, Input } from '@angular/core'; import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms'; @Directive({ selector: '[appForbiddenNames]', providers: [{ provide: NG_VALIDATORS, useExisting: ForbiddenNamesDirective, multi: true }] }) export class ForbiddenNamesDirective implements Validator { // 把单一字符串改成数组类型,默认空数组避免报错 @Input() forbiddenNames: string[] = []; validate(control: AbstractControl): { [key: string]: any } | null { // 如果没有传入禁用名称,直接跳过验证 if (!this.forbiddenNames.length) return null; // 检查输入值是否匹配禁用列表中的任意一项(不区分大小写) const isForbidden = this.forbiddenNames.some( name => control.value?.toLowerCase() === name.toLowerCase() ); return isForbidden ? { 'forbiddenName': { value: control.value } } : null; } }
模板中使用:
<!-- 传入多个禁用名称数组 --> <input type="text" appForbiddenNames [forbiddenNames]="['admin', 'root', 'superuser']" placeholder="不能输入admin/root/superuser" />
二、改用
Object类型的@Input(支持复杂验证规则) 如果需要更灵活的配置(比如区分大小写、自定义提示信息等),用Object类型的@Input能承载更多元的规则。
指令代码调整:
import { Directive, Input } from '@angular/core'; import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms'; @Directive({ selector: '[appForbiddenConfig]', providers: [{ provide: NG_VALIDATORS, useExisting: ForbiddenConfigDirective, multi: true }] }) export class ForbiddenConfigDirective implements Validator { // 定义包含规则的对象类型,默认值确保不会报错 @Input() forbiddenConfig: { names: string[]; caseSensitive?: boolean; customMessage?: string } = { names: [], caseSensitive: false }; validate(control: AbstractControl): { [key: string]: any } | null { const { names, caseSensitive } = this.forbiddenConfig; if (!names.length) return null; // 根据是否区分大小写处理输入值和禁用列表 const inputValue = caseSensitive ? control.value : control.value?.toLowerCase(); const processedForbiddenNames = caseSensitive ? names : names.map(name => name.toLowerCase()); const isForbidden = processedForbiddenNames.includes(inputValue); // 可以把自定义配置返回给模板,方便显示自定义提示 return isForbidden ? { 'forbiddenName': { value: control.value, forbiddenNames: names, message: this.forbiddenConfig.customMessage || '输入内容已被禁用' } } : null; } }
模板中使用:
<!-- 区分大小写的禁用配置 --> <input type="text" appForbiddenConfig [forbiddenConfig]="{ names: ['Admin', 'Root'], caseSensitive: true, customMessage: '不能输入大写的Admin/Root' }" /> <!-- 不区分大小写的禁用配置 --> <input type="text" appForbiddenConfig [forbiddenConfig]="{ names: ['guest', 'test'], caseSensitive: false, customMessage: '不能输入guest/test(不区分大小写)' }" />
三、退而求其次:用多个独立
@Input传参(不推荐) 如果实在不想用数组或对象,也可以定义多个独立的@Input属性,然后在验证器里合并检查。但这种方式扩展性差,参数多了会很繁琐,只适合参数极少的场景。
指令代码示例:
@Input() forbiddenName1: string = ''; @Input() forbiddenName2: string = ''; validate(control: AbstractControl): { [key: string]: any } | null { // 过滤掉空值,合并成数组 const forbiddenNames = [this.forbiddenName1, this.forbiddenName2].filter(Boolean); const isForbidden = forbiddenNames.some( name => control.value?.toLowerCase() === name.toLowerCase() ); return isForbidden ? { 'forbiddenName': { value: control.value } } : null; }
模板中使用:
<input type="text" appForbiddenNames [forbiddenName1]="'admin'" [forbiddenName2]="'root'" />
内容的提问来源于stack exchange,提问作者Ka Mok
相关产品推荐
相关产品推荐

