Передайте дополнительные аргументы декоратору метода внутри углового компонента - PullRequest
0 голосов
/ 01 апреля 2019

Допустим, у нас есть много методов, в которые мы хотим добавить диалог подтверждения к исходному методу.Поэтому мы решили создать собственный декоратор.

@Component({...})
export class HeroComponent {
  constructor(private dialog: MatDialog) {}

  @confirmByDialog(this.dialog)
  deleteHero() { ... }
}

export function confirmByDialog (dialog: MatDialog): MethodDecorator {
  return (target: Function, key: string, descriptor: any) => {
    const originalMethod = descriptor.value;

    descriptor.value = (...args: any[]) => {
      const dialogRef = dialog.open(ConfirmationDialogComponent);
      return dialogRef
        .afterClosed()
        .subscribe((confirmed: boolean) => {
          if (confirmed) {
            originalMethod();
          }
        });
    };

    return descriptor;
  };
}

Но этот подход не работает из-за

Невозможно прочитать свойство 'диалог' из неопределенного (hero.component.ts)

Как передать дополнительные параметры декоратору?Я уже думал о передаче dialog самой исходной функции для доступа к ней через args, но для меня это звучит как очень грязный хак?

Заранее спасибо!

1 Ответ

2 голосов
/ 01 апреля 2019

Вы не можете получить доступ к полям экземпляра в параметрах декоратора.Декоратор применяется для класса, а не для экземпляра.

Простым решением является передача имени диалогового поля, но это означает, что поле должно быть общедоступным.

Вам также нужно изменить способ пересылки параметров и this.Так как нам нужен доступ к фактическому, переданному в этом, мы не можем использовать функцию стрелки, и нам нужно использовать apply для пересылки this

class HeroComponent {
  constructor(public dialog: MatDialog) { }

  @confirmByDialog("dialog") // Checked by the compiler.
  deleteHero() { }
}
function confirmByDialog<K extends string>(dialog: K) {
  return (target: Record<K, MatDialog>, key: string, descriptor: any) => {
    const originalMethod: Function = descriptor.value;

    descriptor.value = function (this: Record<K, MatDialog>, ...args: any[]) {
      const dialogRef = this[dialog].open(ConfirmationDialogComponent);
      return dialogRef
        .afterClosed()
        .subscribe((confirmed: boolean) => {
          if (confirmed) {
            originalMethod.apply(this, ...args);
          }
        });
    };
    return descriptor;
  };
}
...