我正在尝试使用装饰器将验证器方法传递到 angular4 响应式形式以进行验证。
组件
@AutoUnsubscribe( [] )
@Component(
{
selector: 'pim-mat-input',
template: `
<form
autocomplete = 'off'
[formGroup] = 'form'>
<section
fxLayout = 'column'
fxLayoutAlign = 'start start'>
<mat-form-field>
<input
#input
matInput
formControlName = 'entry'>
</mat-form-field>
</section>
</form>
`,
styles: []
} )
export class PimMatInputComponent implements AfterViewInit, OnDestroy, OnInit {
protected entryCtrl: AbstractControl
protected form: FormGroup
constructor( private _fb: FormBuilder ) {
}
@validators( [ PimNgxFormValidators.notEmpty ] )
ngOnInit() {
this.form = this._fb.group(
{ entry: [ '', [ /*PimNgxFormValidators.notEmpty goes here*/] ] } )
this.entryCtrl = this.form.controls[ 'entry' ]
}
ngOnDestroy() {
// needed for @AutoUnsubscribe()
}
ngAfterViewInit(): void {
}
}
装饰器尝试 - 不完整
export function validators( vals: Array<Function> = [] ) {
let form: FormGroup
return function( target: any, member: string, descriptor: PropertyDescriptor ) {
const originalMethod = descriptor.value
descriptor.value = function( ...args ) {
// What should I put here to allow the argument to be used in the component
}
return descriptor
}
}
如何让装饰器将其参数传递给表单中的入口控件?
干杯
最佳答案
尝试类似的东西
export function validators(...vals: Array<(...args: any[]) => void>) {
let form: FormGroup
return function <T extends object>(target: T, key: keyof T, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value
descriptor.value = function(...args: any[]) {
performValidation(...args);
originalMethod.call(target, ...args);
}
return descriptor;
}
}
泛型的原因很简单,就是保证方法是由目标对象定义的。这不是必需的,但我觉得它很有值(value)。
在调用方法时将验证数组 vals
传递给框架比较复杂。
最简单的方法是将验证器本身存储在类的一个字段中,这样它们就可以使用了,但这有点违背了使用装饰器的目的。
例如我们可以这样写
export function validators(...vals: Array<(...args: any[]) => void>) {
return function <T extends {validators: Array<(...args: any[]) => void>}>(target: T) {
target.validators = vals;
}
}
这样我们的类(class)看起来像
export class PimMatInputComponent {
validators: (...vals: Array<(...args: any[]) => void> = [];
@validators([PimNgxFormValidators.notEmpty])
ngOnInit() {
this.form = this._fb.group({
entry: [ '', [this.validators]]
});
this.entryCtrl = this.form.controls['entry'];
}
}
如您所见,在这种情况下我们没有触及描述符,因为我们只是使用装饰器将验证器附加到类。但这使得装饰器的使用变得多余,因为我们可以更易读地编写
export class PimMatInputComponent {
validators = [PimNgxFormValidators.notEmpty];
ngOnInit() {
this.form = this._fb.group({
entry: [ '', [this.validators]]
});
this.entryCtrl = this.form.controls['entry'];
}
}
方法装饰器对于验证包装方法体很有用。它们通常可用于验证方法的参数,但不能将代码注入(inject)实现本身。
例如,如果我们希望验证传递给方法的参数,我们可以编写一个像这样的装饰器
export function validateArguments(...validators: Array<(...as: any[]) => void>) {
return <T extends object>(target, key: keyof T, descriptor: PropertyDescriptor) => {
const originalMethod = descriptor.value;
descriptor.value = (...args: any[]) => {
args.forEach(argument => {
validators.forEach(validate => {
validate(argument);
});
});
originalMethod.call(target, ...args);
};
};
}
然后我们可以将它应用于任意方法并按如下方式传入验证器
export class A {
@validateArguments(arg => {
if (arg === undefined) {
throw Error('required parameter not specified');
}
})
m(a, b, c) {
console.log('If we got here no arguments were undefined.');
}
}
关于typescript - 创建一个将参数传递给 angular4 ngOnInit() 的装饰器方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46679298/