当令牌可以是多个值时,通过 Injector.get() 获取父组件

Edw*_*ard 3 angular2-injection angular

我正在尝试做的事情:

  • 使用单个指令的多个不同组件
  • 当指令被调用时,我需要能够获取指令被调用的父/主机组件。

Plnkr -> http://plnkr.co/edit/Do4qYfDLtarRQQEBphW3?p=preview

在查看 angular.io 文档时,我发现“Injector”可用于获取构造函数中的父组件

constructor(private el: ElementRef, private hostComponent:Injector){
    el.nativeElement.draggable = 'true';
}
Run Code Online (Sandbox Code Playgroud)

在这样做时,我得到了 Injector Object。据我所知,我应该使用

this.hostComponent.get(INJECTORTOKEN)
Run Code Online (Sandbox Code Playgroud)

我难以理解的问题是,Angular 中提供的示例假设您知道要在令牌中提供的 Component 类型。IE:

this.hostComponent.get(Image);
this.hostComponent.get(Box);
Run Code Online (Sandbox Code Playgroud)

在 pnkr 示例中,我的模板中有两个组件

<div>
   <h2>Hello {{name}}</h2>
   <my-image></my-image> <!-- Uses the "My Directive" -->
   <my-box></my-box> <!-- Uses the "My Directive" -->
</div>
Run Code Online (Sandbox Code Playgroud)

我的问题是,在“mydirective.ts”中。当我不知道父组件是“my-image”还是“my-box”组件时,如何利用“injector.get()”。

在提供的示例中,指令被触发“ondrag()”。查看控制台,获取日志消息。

非常感谢任何帮助。

非常感谢你。

yur*_*zui 5

我知道有几种方法可以做到这一点:

1)通过它的类接口找到一个父级

您需要提供者的类接口令牌,例如:

export abstract class Parent { }
Run Code Online (Sandbox Code Playgroud)

在此之后,你应该写上一个别名供应商BoxImage组件

box.ts

providers: [{ provide: Parent, useExisting: forwardRef(() => Box) }]
Run Code Online (Sandbox Code Playgroud)

图像.ts

providers: [{ provide: Parent, useExisting: forwardRef(() => Image) }]
Run Code Online (Sandbox Code Playgroud)

然后在您的指令中使用它,如下所示

我的指令.ts

export class MyDirective {
  constructor(@Optional() private parent: Parent){}

  @HostListener('dragstart',['$event']) ondragstart(event){
    switch(this.parent.constructor) {
     case Box:
      console.log('This is Box');
      break;
     case Image:
      console.log('This is Image');
      break;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这里是普朗克

2)注入你所有的父母作为Optional令牌

我的指令.ts

export class MyDirective {
  constructor(
    @Optional() private image: Image, 
    @Optional() private box: Box){}

    @HostListener('dragstart',['$event']) ondragstart(event){
      if(this.box) {
        console.log('This is Box');
      }
      if(this.image) {
        console.log('This is Image');
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Plunker这种情况

3)使用Injector喜欢

export class MyDirective {
  constructor(private injector: Injector){}

  @HostListener('dragstart',['$event']) ondragstart(event){
    const boxComp = this.injector.get(Box, 0);
    const imageComp = this.injector.get(Image, 0);

    if(boxComp) {
      console.log('This is Box');
    }
    if(imageComp) {
      console.log('This is Image');
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

普朗克