您要查找的模式肯定是可能的,但不能通过指令来实现您想要的意义。这是因为Angular是编译型的,这意味着您无法“硬编码”指令(至少不建议在生产中这样做,否则会出现奇怪的问题)。
您的组件可以接受名为
validators
的输入,该输入应为函数数组(或类的实例,如果需要),然后使用它进行验证。
例如,您可以拥有以下三个超级简单的验证器:
export const required = value => value != null && value != ''
export const minLength3 = value => value == null || value.length > 3
export const maxLength9 = value => value == null || value.length < 9
您的
my-component
接受这些验证器的数组。为简单起见,验证器实际上是一个字符串的谓词。换句话说,它是一个与上面三个函数具有相同签名的函数:
(value: string) => boolean
。我们将此输入初始化为空数组,有效地使其成为默认值,以防未传递任何内容。
@Input() validators: ((value: string) => boolean)[] = []
在使用
my-component
组件的消费者组件模板中,我们现在通过向其传递一个验证器数组来使用该组件。
<my-component [validators]="[required, maxLength9]"></my-component>
当然,要使用它们,我们必须将它们作为组件类的成员进行DI或简单实例化。要与DI一起使用验证器,验证器必须是类(至少在5.x.x及以下版本中)。
import {required, maxLength9} from '../validators'
export class ConsumerComponent {
public required = requierd
public maxLength9 = maxLength9
}
“my-component” 组件当然应该使用这些验证器。例如,可以在每个 “change”、 “input” 或 “blur” 事件上运行以下函数,具体取决于您想何时运行验证器。
public validate(value: string): boolean {
let valid: boolean = true
this.validators.forEach(validator => {
const result = validator(value)
valid = valid || result
})
}
现在你可以更好地动态控制想要在字段上运行的验证器。当然,在应用程序运行时也可以动态更改这些内容。但是,这样做会带来以下代价:无法摇树(tree-shaking)未使用的验证器。Angular编译器无法确定您正在使用哪些验证器,这意味着所有验证器都必须被导入到您的应用程序的最终捆绑包中,即使其中一些可能永远不会被使用。
您可能会对Angular中的响应式表单感兴趣。您可以阅读官方文档中的响应式表单, 或查看Todd Motto在Angular中的响应式表单文章, 或Pascal Precht在thoughtram上的Angular响应式表单。