Angular template and transclusion: content out of order

1.6k views Asked by At

I'm facing some challenges with Angular content projection. I have a template that has some common HTML for every instance that will be used, and another part that will be subject to change from case to case, via transclusion (ng-content). The problem is that no matter the order I use on my template DOM elements , the output is always the same. Here's the code:

<ng-template #lol>
  <ng-content select=".world"></ng-content>
  <div>Hello</div>
</ng-template>

<ng-container [ngTemplateOutlet]="lol">
  <div class="world">World</div>
</ng-container>

I would expect the produced result to be:

World
Hello

given that I'm placing first the transcluded element and only then the static part of the template. But even if I switch their order on the template, the result will always be:

Hello
World

And I can't understand why. Can someone please shed some lights on why this is happening and what can I do to produce the output I want? Thank you.

NOTE: Here's a StackBlitz with a full example: https://stackblitz.com/edit/angular-vfecbs?file=src%2Fapp%2Fapp.component.html

3

There are 3 answers

2
SiddAjmera On

You probably are not using it correctly. Suppose that you're using the template code that you've specified in the OP in a Component named HelloComponent.

It should then be used like this:

<app-hello>
  <p class="world">Some projected Content</p>
</app-hello>

HEre's a Sample StackBlitz for your ref.

1
Sheik Althaf On

ng-content have special power where you place it, there it will replace the select content.

<ng-template #lol>
  <ng-content select=".world"></ng-content> <--- World will be printed here
  <div>Hello</div>
</ng-template>

Make sure where you add the ng-content there will be select content replaced. If you need Hello in up simply move the element first

<ng-template #lol>
  <div>Hello</div>
  <ng-content select=".world"></ng-content> <--- World will be printed
</ng-template>
0
Rahul On

Content projection is the concept of projecting a content from one component to another - if you are passing some value to you child component from parent component and the value changes dynamically then you can go for Content projection

In your case the whole <ng-template> gets passed to your <ng-container> thus it reads as Hello, World - there is nothing happening with the <ng-content> remove it you might find the same result

<ng-container [ngTemplateOutlet]="lol">
  <div>Hello</div>
  <div class="world">World</div>
</ng-container>

Your output will be like this when you inspect your code - thus only the <div>Hello</div> gets embedded inside your container - it doesn't pass any content form it to the <ng-template> - so that seems not a way to fix it

Try by passing the content from one component to another check this link

Hope it helps - happy coding :)