Angular Styling viewContainerRef aus dem Directive Input Array
Ich habe eine Direktive erstellt, die ein Array mit variabler Länge verwendet, um einen Tooltip zu füllen. Dies funktioniert hervorragend, aber ich muss den Tooltip dynamisch formatieren, damit er unter der anfänglichen Triggerkomponente bleibt. Verwenden eines oberen oder unteren Werts, der sich je nach Anzahl der Elemente ändert.
<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>
Ich habe versucht, ngStyle zu verwenden, bin mir jedoch nicht sicher, wie ich auf den divStyle-Wert zugreifen soll, da dieser mit viewContainerRef.createEmbeddedView erstellt wird.
Ich dachte, eine bessere Option wäre, die Stile aus der ts-Datei mit style.bottom hinzuzufügen, aber ich weiß nicht, wie ich das hinzufügen soll. Ich muss tooltipDataArray.length berechnen und dann etwa 10 Pixel zu einer Variablen hinzufügen, die den viewContainerRef neu positioniert. Ich bin mir nicht sicher, wie ich am besten vorgehen soll.
@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 hier
Antworten
Wenn Sie bereit wären, das templateRefals Input für die Richtlinie weiterzugeben, wäre dies viel einfacher ...
Mit Ihrer aktuellen Implementierung ersetzen Sie den Inhalt
divder Vorlage durch den gerenderten Inhalt der Vorlage ...
- Dies ist im Wesentlichen kein Tooltip, und Sie müssten sie irgendwie entkoppeln, um "einen Tooltip zu simulieren".
Im Folgenden finden Sie eine Möglichkeit, dies zu erreichen.
Trennen Sie die ng-templatevon der div, um sie zu entkoppeln, und übergeben Sie Ihre #tooltipTemplateals Wert an die [templateRef]Eingabe auf derdirective
<div tooltipDirective [templateRef]="tooltipTemplate" [tooltipDataArray]="['Person1', 'Person2']">See tooltip!
</div>
<ng-template #tooltipTemplate>
<div class="tooltip">
This is my tooltip!
</div>
</ng-template>
Konvertieren Sie @ContentChildin Ihrer Direktive Ihre in eine Eingabe, um die zu erhalten templateRef, erstellen Sie Ihre embeddedViewund fügen Sie Ihre arrayElemente hinzu.
- Dies vereinfacht auch hier Ihre Logik
@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);
});
}
Passen Sie Ihr globales Styling an
.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
Dies wäre die sauberste Implementierung mit dem von Ihnen bereitgestellten Gerüst. Wenn ich eine Tooltip-Direktive implementieren würde, würde ich CDK Overlaynach einer benutzerdefinierten Tooltip-Implementierung suchen.