11

I would like to render content from one element in QueryList filled by ContentChildren.

Let's say I want to build tab component and this is my template for using such component:

<my-tabs>
  <my-tab title="title1">some content 1<my-tab>
  <my-tab title="title2">some content 2<my-tab>
</my-tabs>

My current tabs component html:

<div class="header">
  <ul>
    <li> *ngFor="let tab of tabs, let i = index; let isLast = last">...<li>
  </ul>        
</div>
<!-- Missing !!! -->

Code:

@ContentChildren(MyTabComponent) public tabs: QueryList<MyTabComponent>;

My problem is how can I render only active tab? (<!-- Missing !!! -->)

I tried:

<ng-container [ngComponentOutlet]="tabs.toArray()[currentIndex].content"></ng-container>

<ng-container [ngTemplatetOutlet]="tabs.toArray()[currentIndex].content"></ng-container>    

<ng-container [ngComponentOutlet]="tabs.toArray()[currentIndex]"></ng-container>

<ng-container [ngTemplatetOutlet]="tabs.toArray()[currentIndex]"></ng-container>

But tab content is never rendered. my-tab component html is just:

<div>body</div>
<ng-template><ng-content></ng-content></ng-template>

at the moment.

I check online how others are solving this problems, but everyone are using just <ng-content></ng-content> and then hides inactive tabs.
But I think better would be to render only needed content (better performance).

I also found this code where <ng-container [ngTemplateOutlet]="step.content"></ng-container> is used, but I tried this approach and it doesn't render anything.

Edited:
I also prepare stackblitz.

Adrien Brunelat
  • 4,492
  • 4
  • 29
  • 42
Makla
  • 9,899
  • 16
  • 72
  • 142

1 Answers1

12

Use ViewChild inside your StepComponent for storing element (in your case ng-template):

@Component({
    selector: "my-step",
    template: "<ng-template #innerTemplate><ng-content></ng-content></ng-template>",
})
export class StepComponent 
{
    @Input()
    public title;

    @ViewChild('innerTemplate') 
    public innerTemplate: TemplateRef<any>;
}

And set ngTemplateOutlet to that property in StepperComponent:

<ng-template [ngTemplateOutlet]="step.innerTemplate"></ng-template>

Here is the forked StackBlitz.

Farhad Jabiyev
  • 26,014
  • 8
  • 72
  • 98
  • 1
    Would have been nice to use the main example above. Also, in the parent I needed to use ng-content instead of ng-template to see something. ``. Thank you for providing this answer, I was already searching for a bit! – hogan Jul 15 '19 at 11:31
  • 2
    Thats very confusing if you provide a different example. Could you change this solution to use tab and not step so that we all dont need to figure out what goes where? – hogan Nov 27 '19 at 11:19