在指令中手动获取Injector的依赖关系

时间:2016-11-10 20:26:25

标签: javascript angular typescript

我正在尝试创建一个泛型指令,该指令将采用类类型进行规则验证,并且根据类中的规则,该指令将显示或隐藏元素。

这是我迄今为止的尝试。

PLUNKER演示

myIf-Directive.ts

@Directive({
  selector: '[myIf]'
})
export class MyIfDirective {
  constructor(private _viewContainer: ViewContainerRef,
    private _template: TemplateRef<Object>) 
  { }

  @Input() set myIf(rule: string) {
    //rule class type will come as string
    //how can I use string token to get dependency from injector?
    //currently harcoded
    //will the injector create new instance or pass on instance from parent?
    let injector = ReflectiveInjector.resolveAndCreate([AdminOnly]);
    let adminOnly : IRule = injector.get(AdminOnly);
    let show = adminOnly.shouldShowElement();
    show ? this.showItem() : this.hideItem();
  }
  private showItem() {
    this._viewContainer.createEmbeddedView(this._template);
  }

  private hideItem() {
    this._viewContainer.clear();
  }
}


应用-component.ts

@Component({
  selector: 'my-app',
  template: `
    <div *myIf="'AdminOnly'">
      <h2>Hello {{name}}</h2>
    </div>
  `,
})
export class App {
  name:string;
  constructor() {
    this.name = 'Angular2'
  }
}

但我被困在两个地方:

  1. 我不断收到错误No Provider for AuthService
  2. 我不知道如何使用类名作为字符串而不是类型
  3. 从Injector获取依赖项

    有任何关于这是正确的做法还是出错的建议都非常感谢。

2 个答案:

答案 0 :(得分:3)

您需要传递父注入器,如

export class MyIfDirective {
  constructor(private injector:Injector, private _viewContainer: ViewContainerRef,
    private _template: TemplateRef<Object>) 
  { }

  @Input() set myIf(rule: string) {
    let resolvedProviders = ReflectiveInjector.resolve([AdminOnly]);
    let childInjector = ReflectiveInjector.fromResolvedProviders(resolvedProviders, this.injector);

    let adminOnly : IRule = childInjector.get(AdminOnly);
    let show = adminOnly.shouldShowElement();
    show ? this.showItem() : this.hideItem();
  }
  private showItem() {
    this._viewContainer.createEmbeddedView(this._template);
  }

  private hideItem() {
    this._viewContainer.clear();
  }
}

另见Inject service with ReflectiveInjector without specifying all classes in the dependency tree

答案 1 :(得分:0)

仅针对Angular 10+版本进行了更新:

  • 通过您的服务:
  @Injectable({
    providedIn: 'any'
  })
  export class AdminOnly { ... }
  • 在您的指令或纯函数中,...:
 import { Injector } from '@angular/core';

 ...
 const injector: Injector = Injector.create({
   providers: [{provide: AdminOnly, deps: []}]
 });
 const adminOnly: AdminOnly = injector.get(AdminOnly);

 let show = adminOnly.shouldShowElement();
 ...

See more