Angular 指令输入数组中的样式 viewContainerRef
Angular styling viewContainerRef from Directive Input array
我创建了一个使用可变长度数组来填充工具提示的指令。这很好用,但我需要动态设置工具提示的样式,以便它保留在初始触发器组件下。使用根据项目数量变化的最高值或最低值。
<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();
}
如果您愿意将 templateRef
作为输入传递给指令,这会容易得多...
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"
下面是您可以完成此操作的一种方法。
将 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
元素。
- 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);
});
}
调整全局样式
.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
这将是使用您提供的脚手架实现的最干净的实现...话虽如此,如果我要实现工具提示指令,我会研究 CDK Overlay
以创建自定义工具提示实现。
我创建了一个使用可变长度数组来填充工具提示的指令。这很好用,但我需要动态设置工具提示的样式,以便它保留在初始触发器组件下。使用根据项目数量变化的最高值或最低值。
<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();
}
如果您愿意将 templateRef
作为输入传递给指令,这会容易得多...
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"
下面是您可以完成此操作的一种方法。
将 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
元素。
- 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);
});
}
调整全局样式
.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
这将是使用您提供的脚手架实现的最干净的实现...话虽如此,如果我要实现工具提示指令,我会研究 CDK Overlay
以创建自定义工具提示实现。