Передача данных во всплывающую подсказку Angular 2 - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть следующая директива и компоненты

TooltipDirective.ts

    import { Directive, TemplateRef, Input, Type, ComponentRef, ElementRef, 
Renderer2, Injector, ComponentFactoryResolver, ViewContainerRef, 
HostListener, ReflectiveInjector } from '@angular/core';
import { TooltipComponent } from '../components/tooltip/tooltip.component';

@Directive({
  selector: '[tooltip]'
})
export class TooltipDirective {
  @Input('tooltip') content: string | TemplateRef<any> | Type<any>;

  private componentRef: ComponentRef<TooltipComponent>;

  constructor(private element: ElementRef,
    private renderer: Renderer2,
    private injector: Injector,
    private resolver: ComponentFactoryResolver,
    private vcr: ViewContainerRef) { }

  @HostListener('mouseenter')
  mouseenter() {
    if (this.componentRef) return;
    const factory = this.resolver.resolveComponentFactory(TooltipComponent);
    const injector = ReflectiveInjector.resolveAndCreate([
      {
        provide: 'tooltipConfig',
        useValue: {
          host: this.element.nativeElement
        }
      }
    ]);
    this.componentRef = this.vcr.createComponent(factory, 0, injector, 
this.generateNgContent());
  }

  generateNgContent() {
    if (typeof this.content === 'string') {
      const element = this.renderer.createText(this.content);
      return [[element]];
    }

    if (this.content instanceof TemplateRef) {

      const context = {};
      const viewRef = this.content.createEmbeddedView(context);
      // In earlier versions, you may need to add this line
      // this.appRef.attachView(viewRef);
      return [viewRef.rootNodes];
    }

    // Else it's a component
    const factory = this.resolver.resolveComponentFactory(this.content);
    const componentRef = factory.create(this.injector);
    // In earlier versions, you may need to add this line
    // this.appRef.attachView(componentRef.hostView);
    return [[componentRef.location.nativeElement]];
  }

  @HostListener('mouseout')
  mouseout() {
    this.destroy();
  }

  destroy() {
    this.componentRef && this.componentRef.destroy();
    this.componentRef = null;
  }

  ngOnDestroy() {
    this.destroy();
  }

}

tooltip.component.ts

import { Component, OnInit, Directive, ViewChild, ElementRef, Inject } from '@angular/core';

@Directive({
  selector: '.tooltip-container'
})
export class TooltipContainerDirective {
}

@Component({
  selector: 'yl-tooltip',
  templateUrl: './tooltip.component.html',
  styleUrls: ['./tooltip.component.scss']
})
export class TooltipComponent implements OnInit {
  top : string;
  @ViewChild(TooltipContainerDirective, { read: ElementRef }) private tooltipContainer;

  constructor(@Inject('tooltipConfig') private config) { }

  ngOnInit() {
     // For simplicity, we calculate only the top.
     const { top } = this.config.host.getBoundingClientRect();
     const { height } = this.tooltipContainer.nativeElement.getBoundingClientRect();
     this.top = `${top - height}px`;
  }

}

tooltip.component.html

<div class="tooltip-container" [ngStyle]="{top: top}">
  <ng-content></ng-content>
</div>

Я пытаюсь реализовать эту подсказку внутри * ngFor следующим образом:

<div *ngFor="let member of data">
<div  [tooltip]="template"> This is user {{menber.Name}}</div>
<ng-template #template>
    <div class="tooltip">
      <div>{{member.Amount}}</div>
  </div>
  </ng-template>
</div>

Но подсказка не привязывает значение menber.Amount.Я использую шаблон, поскольку мне нужно сформировать всплывающую подсказку с пользовательским содержимым HTML. Чего мне здесь не хватает?

...