angular - Send et ng-template-element til en direktiv


Jeg prøver å sende et ng-template til direktivet mitt, noe slikt som dette:

komponent.html

<div myDirective [myTemplate]="myTemplate"></div>
<ng-template #myTemplate><p>Lorem ipsum dolor sit amet.</p></ng-template> 

directive.ts

import {Directive, Input} from "@angular/core"

@Directive({
  selector: "[myDirective]"
})
export class MyDirective {
  @Input() myTemplate

  ngOnInit () {
    console.log(this.myTemplate.elementRef.nativeElement)
  }
}

Men det viser bare <!-- -->. Hvordan får jeg tilgang til innholdet i malen? Ingen av de andre egenskapene ser ut til å ha det - kommentarer på dette spørsmålet foreslår å bruke templateRef i stedet, men det er udefinert.

Stackblitz om nødvendig.

For å klargjøre, er det endelige målet med direktivet å betinget legge til innholdet i malen til dens overordnede element (sammen med noen andre endringer).

Svar #1

Som du kan se på angular.io :

Ng-template er et Angular-element for å gjengi HTML. Det vises aldri direkte. Faktisk, før visningen gjengis, erstatter Angular ng-template og innholdet med en kommentar.

Så ved kjøretid er ng-template bare en kommentar. Den kan ikke rendres som en DOM, og det er umulig å nå den som ElementRef-typen.

Men hvis du for eksempel vil sende et p-element til direktivet ditt, er det mulig. Jeg endret koden din for å gjøre det. Se dette Stackblitz-prosjektet:

https://stackblitz.com

Svar #2

Jeg har en popup-direktiv for å håndtere posisjonering av popup-vinduer i DOM-en. Jeg plasserer direktivet på en knapp eller lenke og sender det popup-elementet. Direktivet posisjonerer deretter popup-vinduet i DOM-en.

Direktivet støtter både et vanlig HTML-element og et ng-template-element som en popup.

For klarhetens skyld inneholder koden nedenfor bare deler som er relevante for spørsmålet.

import { Directive, ElementRef, Input, OnInit, TemplateRef, ViewContainerRef } from "@angular/core";
    
    
@Directive({
    selector: '[ui-popup]'
})
export class UIPopupDirective implements OnInit, OnDestroy {
      
  constructor(private el: ElementRef, private containerRef: ViewContainerRef) { }

  @Input() popupTemplate: HTMLElement;
  @Input() popupNgTemplate: TemplateRef<any>;
  @Input() data:any;
  
  ngOnInit() {
     if (this.popupNgTemplate) {
      const embeddedViewRef = this.containerRef.createEmbeddedView(this.popupNgTemplate, {
        item: this.data
      });
      embeddedViewRef.detectChanges();
      this.popupTemplate = embeddedViewRef.rootNodes[0];
    }
}

Eksempler på bruk:

<button type="button" ui-popup [popupTemplate]="regularTag">Click to say hello</button>

<div #regularTag>Hello</div>

... eller ...

<button type="button" ui-popup [popupNgTemplate]="ngTemplateTag">Click to discover the world</button>

<ng-template #ngTemplateTag><div>World</div></ng-template>

Relaterte artikler