Получение родительского компонента через Injector.get(), когда токен может иметь несколько значений

#angular #angular2-injection

#angular #angular2-инъекция

Вопрос:

Что я пытаюсь сделать:

  • Несколько разных компонентов, которые используют одну директиву
  • при вызове директивы мне нужно иметь возможность получить родительский / хост-компонент, из которого вызывается директива.

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

При рассмотрении angular.io документация, я обнаружил, что «Инжектор» можно использовать для получения родительского компонента в конструкторе

 constructor(private el: ElementRef, private hostComponent:Injector){
    el.nativeElement.draggable = 'true';
}
  

При этом я получаю объект инжектора. Из того, что я могу сказать, я должен использовать

 this.hostComponent.get(INJECTORTOKEN)
  

Проблемы, которые мне трудно понять, заключаются в том, что в примерах, приведенных в Angular, предполагается, что вы знаете тип компонента, который нужно указать в token. ie:

 this.hostComponent.get(Image);
this.hostComponent.get(Box);
  

В примере pnkr у меня есть два компонента в моем шаблоне

 <div>
   <h2>Hello {{name}}</h2>
   <my-image></my-image> <!-- Uses the "My Directive" -->
   <my-box></my-box> <!-- Uses the "My Directive" -->
</div>
  

Мои вопросы в «mydirective.ts». как я могу использовать «injector.get ()», когда я не знаю, является ли родительский компонент компонентом «my-image» или «my-box».

в предоставленном примере директива запускается «ondrag()». просмотрите консоль для получения сообщений журнала.

Любая помощь приветствуется с благодарностью.

Большое спасибо.

Ответ №1:

Я знаю несколько способов сделать это:

1) Найдите родительский элемент по его классу-интерфейсу

Вам нужен токен интерфейса класса поставщика, например:

 export abstract class Parent { }
  

После этого вы должны написать псевдоним поставщика Box и Image компонента

box.ts

 providers: [{ provide: Parent, useExisting: forwardRef(() => Box) }]
  

image.ts

 providers: [{ provide: Parent, useExisting: forwardRef(() => Image) }]
  

затем используйте его в своей директиве, как показано ниже

myDirective.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;
    }
  }
}
  

Вот Plunker

2) Введите всех своих родителей в качестве Optional токена

myDirective.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');
    }
  }
}
  

Плунжер для этого случая

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');
    }
  }
}
  

Плунжер

Комментарии:

1. Большое вам спасибо. это решило проблему и также предлагает мне путь вперед по ряду различных проблем. Merci Beaucoup!