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

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

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

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

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

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

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

this.hostComponent.get(INJECTORTOKEN)

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

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

Вот плункер

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

Plunker

Другие вопросы по тегам