как передать TemplateRef в директиву?

#angular

#угловатый

Вопрос:

я пытаюсь создать пользовательскую директиву всплывающей подсказки в angular, и я хочу передать TemplateRef в качестве входного свойства этой директиве из родительского компонента, но TemplateRef.ElementRef возвращает комментарий вместо содержимого шаблона.

Директива:

 @Directive({
  selector: '[tooltip]'
})
export class tooltipDirective {
  @Input('tooltip') tooltip: ElementRef<any>;
  @Input('placement') placement: string = 'bottom';

  constructor(private el: ElementRef, private renderer: Renderer2) {
    console.log(this.tooltip);
  }
}
 

Родительский компонент:

 <div [tooltip]="tooltipTemplate"> show tooltip </div>

<ng-template #tooltipTemplate>
  <div class="tooltip">
    tooltip text
  </div>
</ng-template>
 

как я могу получить фактический контент?

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

1. Не используйте конструктор (никогда.. действительно).. попробуйте использовать перехват AfterViewInit..

2. @MikeOne, Afterviewinit также дает тот же результат

3. Ах да .. извините. Я пропустил, что вы используете ввод, а не ViewChild.. честно говоря, не уверен, как это передать..

4. ок, нет проблем, спасибо за ваш ответ

Ответ №1:

вы можете использовать в геттере, но будьте осторожны, шаблон — это ссылка на шаблон. Если вы хотите добавить его, введите ViewContainerRef в конструктор, например:

   _tooltip:TemplateRef<any>
  @Input('tooltip') set tooltip(value)
  {
    this._tooltip=value
    this.viewContainer.createEmbeddedView(this._tooltip)
  }
  @Input('placement') placement: string = 'bottom';

  constructor(private viewContainer:ViewContainerRef) {}
 

Обновлено: Об использовании a this.viewContainer.createEmbeddedView(this._tooltip) в целом мы делаем некоторые подобные

     const embeddedViewRef = this.viewContainer.createEmbeddedView( this._tooltip );
    embeddedViewRef.detectChanges(); //<--this makes that if our template
                                     //has a variable and change, the tooltip
                                     //take account this change
 

Затем, для создания инструмента, мы можем использовать Renderer2 для создания div и добавления в div всех узлов embeddedViewRef

   const div = this.renderer.createElement("span");
  embeddedViewRef.rootNodes.forEach(n => {
    this.renderer.appendChild(div, n);
  });
 

Ну, тяжелая работа — вычислить позицию, создать всплывающую подсказку класса и добавить два HostListener для mouseout и mouseover

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

1. какова роль createEmbeddedView?

2. @jagjeet, я обновляю ответ, чтобы дать некоторую подсказку для создания всплывающей подсказки,

3. @Elison Большое спасибо, это идеально, есть только одна проблема, при таком подходе я не могу добавить контекст в шаблон при его использовании

4. я нашел решение для этого, используя вспомогательный компонент вместе с директивой, которую я обновлю здесь, если это сработает