来自指令输入数组的角度样式 viewContainerRef [英] Angular styling viewContainerRef from Directive Input array

查看:20
本文介绍了来自指令输入数组的角度样式 viewContainerRef的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<div tooltipDirective [tooltipDataArray]="['Person1', 'Person2', 'Person3', 'Person4', 'Person5', 'Person6']">查看工具提示!<ng-template #tooltipTemplate ><div class="tooltip"[ngStyle]="{'top.px': divStyle}">//不确定这是否是正确的方法,因为无法绑定到指令中的 divStyle

</ng-模板>

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

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

 @Input() tooltipDataArray: string[];@ContentChild("tooltipTemplate") private tooltipTemplateRef: TemplateRef;@HostListener("mouseenter") onMouseEnter(): void {console.log(this.tooltipDataArray);const 视图 = this.viewContainerRef.createEmbeddedView(this.tooltipTemplateRef);this.tooltipDataArray.forEach(el => {const child = document.createElement(div");child.innerText = el;this.renderer.appendChild(view.rootNodes[1], child);});//类似 this.viewContainerRef.styles.bottom = 10 x this.tooltipDataArray.length + 'px'控制台日志(查看.rootNodes)view.rootNodes.forEach(node => {this.renderer.appendChild(this.elementRef.nativeElement, node);});}@HostListener("mouseleave") onMouseLeave(): void {如果(this.viewContainerRef){this.viewContainerRef.clear();}

stackBlitz 在这里

解决方案

如果您愿意将 templateRef 作为指令的输入传入,这会容易得多...<块引用>

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

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


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

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

<ng-template #tooltipTemplate><div class="tooltip">这是我的工具提示!

</ng-模板>

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

<块引用>
  • 这也简化了您的逻辑

 @Input() templateRef: TemplateRef;@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 {位置:绝对;/* 底部:-40px;*/左:15px;填充:10px;背景:红色;边框半径:5px;/* box-shadow: 0 2px 1px rgba(0, 0, 0, 0.6);*/}

STACKBLITZ

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


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

I have created a directive that uses a variable length array to populate a tooltip. This works great but I need to dynamically style the tooltip so it remains under the initial trigger component. Using a top or bottom value that changes based on the number of items.

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

I tried using ngStyle but am unsure how to get access to the divStyle value because this is created using viewContainerRef.createEmbeddedView.

I thought a better option would be to add the styles from the ts file using style.bottom but I don't know how to add that. I need to calculate tooltipDataArray.length then add 10px or so to a variable that repositions the viewContainerRef. I'm not sure of the best way to proceed.

 @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

解决方案

If you were willing to pass in the templateRef as an input to the directive this would be a lot easier...

With your current implementation you are replacing the content of the div with the rendered content of the template...

  • This essentially is not a tooltip and you would need to decouple them somehow to "simulate a tooltip"


Below is one way you could accomplish this.

Separate the ng-template from the div to decouple them, and pass your #tooltipTemplate as a value to the [templateRef] input on the directive

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

In your directive convert your @ContentChild to an input to receive the templateRef, create your embeddedView and add your array elements.

  • This also simplifies your logic here

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

Adjust your global styling

.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); */
}

STACKBLITZ

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


This would be the cleanest implementation with the scaffolding you have provided... with that said, if I were to implement a tooltip directive, I would research CDK Overlay to create a custom tooltip implementation.

这篇关于来自指令输入数组的角度样式 viewContainerRef的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆