javascript - Visa ng-content två gånger i Angular 10


Jag jobbar i en anpassad Angular-komponent där jag behöver visa det projicerade innehållet två gånger.

Låt oss säga att jag har denna html:

<app-awesome>
    <app-awesome-card *ngFor="let card of cards">
        <h1>{{card.title}}</h1>
        <img [src]="card.thumbnail">
    </app-awesome-card>
</app-awesome>

Så, i awesome-card.component.html kommer det projicerade innehållet att vara några kortkomponenter som jag vill projicera två gånger.

Det skulle kunna vara detta:

<div class="awesome-class">
    <ng-content select="app-awesome-card"></ng-content>
</div>
<div class="more-awesome-class">
    <ng-content select="app-awesome-card"></ng-content>
</div>

Men detta fungerar inte eftersom ng-content bara "klistrar in" mallen, den kan inte dupliceras. Även om jag använder ng-template på det här sättet:

<div class="awesome-class">
    <ng-container *ngTemplateOutlet="content"></ng-container>
</div>
<div class="more-awesome-class">
    <ng-container *ngTemplateOutlet="content"></ng-container>
</div>

<ng-template #content>
    <ng-content select="app-awesome-card"></ng-content>
</ng-template>

Detta kommer inte att fungera heller.

Jag har försökt i en vecka att hitta en elegant lösning men jag kunde inte. Endast genom att modifiera DOM direkt, men det är en dålig praxis. Jag har sett några liknande gamla frågor och till och med en GitHub-förfrågan om detta, men det verkar som att ingen vid den tiden visste svaret.

PD: ContentChild kommer inte heller att fungera eftersom det inte kan se igenom projicerat innehåll (eller något tror jag)

REDIGERA Om jag kunde få tillgång till den projicerade innehållsinformationen, skulle jag kunna rendera innehållet manuellt, men allt jag försökte misslyckades

Svar #1

vad jag kan erbjuda är att skicka en mall istället för att skicka en bit HTML

<app-awesome>
    <ng-template> // or your own helper structural directive can be used.
    <app-awesome-card *ngFor="let card of cards">
        <h1>{{card.title}}</h1>
        <img [src]="card.thumbnail">
    </app-awesome-card>
    </ng-template>
</app-awesome>
@ContentChild(TemplateRef) contentTpl;
...
 
<div class="awesome-class">
    <ng-container *ngTemplateOutlet="contentTpl"></ng-container>
</div>
<div class="more-awesome-class">
    <ng-container *ngTemplateOutlet="contentTpl"></ng-container>
</div>

Svar #2

I mitt fall eftermonterade jag en befintlig komponent och upptäckte problemen med att försöka välja olika utgångar beroende på vyport och hantera ng-content som projicerar ut den sista av sina förekomster.

<div class="mobile">

    ...

    <ng-content></ng-content> <!-- content NOT rendered -->
</div>
<div class="desktop">

    ...

    <ng-content></ng-content> <!-- content rendered here -->
</div>

För att fixa, ersätter jag den sista/andra förekomsten med:

<ng-container *ngTemplateOutlet="contentTemplate"></ng-container>

Och lade till kod bakom det:

@ContentChild(TemplateRef) contentTemplate: TemplateRef<any>;

Dessutom måste innehållet i anroparen omslutas med ng-template, som:

<app-custom-thing class="some-class">
    <ng-template>
        Your content here!
    </ng-template>
</app-custom-thing>

Detta har effekten att tillåta tidigare användning utan omslag i ng-template att fortsätta fungera som det har gjort, medan framtida användning som kräver ng-template kommer att renderas som förväntat.

Nyfiken på om andra har kommentarer eller alternativa metoder att implementera. Tack!

Relaterade artiklar