将附加参数传递给角度组件内的方法装饰器

时间:2019-04-01 13:37:17

标签: angular typescript decorator angular-decorator

比方说,我们有很多方法要向原始方法添加确认对话框。因此,我们决定构建自定义装饰器。

@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 个答案:

答案 0 :(得分:2)

您无法访问装饰器参数中的实例字段。装饰器适用于该类,而不适用于实例。

简单的解决方案是传递对话框字段的名称,但这意味着该字段需要公开。

您还需要更改转发参数和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;
  };
}