typescript - 创建一个将参数传递给 angular4 ngOnInit() 的装饰器方法

标签 typescript typescript-2.5 typescript-decorator

我正在尝试使用装饰器将验证器方法传递到 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/

相关文章:

typescript - JestJS TypeScript : mockImplementation Does not Exist on Type

visual-studio-2013 - 用于构建服务器的 Typescript 1.4 SDK?

javascript - 类型 ORM QueryFailedError PostgreSQL

typescript :映射类型:没有方法的类到接口(interface)

typescript - 如何在 typescript 中为类动态添加装饰器

javascript - Angular 生产版本不能缩短类名吗?

html - 在 Angular HTMl 中动态添加翻转卡

typescript - 未初始化的 TypeScript 类属性不会被迭代

angular - 单击选项卡时,我需要在 angular2 中加载特定组件

typescript - 如何从装饰器中的装饰属性解析属性值的通用类型