【问题标题】:Angular styling viewContainerRef from Directive Input array来自指令输入数组的角度样式 viewContainerRef
【发布时间】:2020-11-12 16:35:55
【问题描述】:

我创建了一个使用可变长度数组填充工具提示的指令。这很好用,但我需要动态设置工具提示的样式,以便它保留在初始触发器组件下。使用根据项目数量变化的顶部或底部值。

<div tooltipDirective [tooltipDataArray]="['Person1', 'Person2', 'Person3', 'Person4', 'Person5', 'Person6']">See tooltip!
 <ng-template #tooltipTemplate > 
  <div class="tooltip" [ngStyle]="{'top.px': divStyle}">   // Not sure if this is the correct approach as can't bind to divStyle in the directive
  </div>      
 </ng-template>  
</div>

我尝试使用 ngStyle,但不确定如何访问 divStyle 值,因为它是使用 viewContainerRef.createEmbeddedView 创建的。

我认为更好的选择是使用 style.bottom 从 ts 文件添加样式,但我不知道如何添加。我需要计算 tooltipDataArray.length,然后将 10px 左右添加到重新定位 viewContainerRef 的变量中。我不确定最好的方法。

 @Input() tooltipDataArray: string[];

 @ContentChild("tooltipTemplate") private tooltipTemplateRef: TemplateRef<Object>;

 @HostListener("mouseenter") onMouseEnter(): void {
  console.log(this.tooltipDataArray);
   const view = this.viewContainerRef.createEmbeddedView(
     this.tooltipTemplateRef
   );

  this.tooltipDataArray.forEach(el => {
  const child = document.createElement("div");
  child.innerText = el;
  this.renderer.appendChild(view.rootNodes[1], child);
  });
  
  // Somthing like this.viewContainerRef.styles.bottom = 10 x this.tooltipDataArray.length + 'px'
  
  console.log(view.rootNodes)
  view.rootNodes.forEach(node => {
  this.renderer.appendChild(this.elementRef.nativeElement, node);
});
}

@HostListener("mouseleave") onMouseLeave(): void {
if (this.viewContainerRef) {
  this.viewContainerRef.clear();
}

stackBlitz here

【问题讨论】:

    标签: angular dom angular-directive


    【解决方案1】:

    如果您愿意将templateRef 作为指令的输入传递,这将容易得多...

    使用您当前的实现,您将替换 div 与模板的渲染内容...

    • 这本质上是 不是工具提示,您需要以某种方式将它们解耦以“模拟工具提示”

    以下是您可以实现此目的的一种方法。

    ng-template 与 div 分离以将它们解耦,并将您的 #tooltipTemplate 作为值传递给 directive 上的 [templateRef] 输入

    <div tooltipDirective [templateRef]="tooltipTemplate" [tooltipDataArray]="['Person1', 'Person2']">See tooltip!
    </div>
    <ng-template #tooltipTemplate>      
        <div class="tooltip">   
            This is my tooltip!
        </div>      
    </ng-template>  
    

    在您的指令中将您的@ContentChild 转换为输入以接收templateRef,创建您的embeddedView 并添加您的array 元素。

    • 这也简化了您的逻辑
      @Input() templateRef: TemplateRef<Object>;
    
      @HostListener("mouseenter") onMouseEnter(): void {
        const view = this.viewContainerRef.createEmbeddedView(this.templateRef);
        this.tooltipDataArray.forEach(el => {
          const child = document.createElement("div");
          child.innerText = el;
          this.renderer.appendChild(view.rootNodes[1], child);
        });
      }
    

    调整全局样式

    .tooltip {
      position: absolute;
      /* bottom: -40px; */
      left: 15px;
      padding: 10px;
      background: red;
      border-radius: 5px;
      /* box-shadow: 0 2px 1px rgba(0, 0, 0, 0.6); */
    }
    

    堆栈闪电战

    https://stackblitz.com/edit/angular-zr2ydx?file=app/tooltip.directive.ts


    这将是您提供的脚手架最干净的实现...话虽如此,如果我要实现工具提示指令,我会研究 CDK Overlay 以创建自定义工具提示实现。

    【讨论】:

    • 谢谢。这很好用,但我会调查 CDK 覆盖。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 2015-02-01
    • 2015-03-04
    • 1970-01-01
    • 2022-06-13
    • 2020-09-19
    • 2019-05-06
    相关资源
    最近更新 更多