Iterate over ng-content items and wrap each in it's own nested div
Asked Answered
P

2

7

I've read this isn't supported yet, but I was wondering if anyone has figured out a hacky workaround for this issue.

What I currently have is a parent component that has this template:

<dxi-item location='after' class="osii-item-content">
    <span><ng-content select="[osii-page-button]"></ng-content></span>
</dxi-item>

Which is creating the following:

<dxi-item location='after' class="osii-item-content">
    <button> // first button returned by ng-content </button>
    <button> // second button returned by ng-content </button>
    <button> // third button returned by ng-content </button>
</dxi-item>

But what I would like it to do, is to net the following html:

<dxi-item location='after' class="osii-item-content">
    <button> // first button returned by ng-content </button>
</dxi-item> 

<dxi-item location='after' class="osii-item-content">
    <button> // second button returned by ng-content </button>
</dxi-item>

<dxi-item location='after' class="osii-item-content">
    <button> // third button returned by ng-content </button>
</dxi-item>

Is there any known workaround for this issue?

Thanks!

Pasho answered 1/10, 2018 at 19:21 Comment(1)
did you ever found how to do it?Moxley
J
3

As a rig you could put all of your buttons in templates in the parent component's content and then iterate through all the templates to display them as content.

App.component.html

<parent_component>
    <ng-template>
        <button> // first button </button>
    </ng-template>
    <ng-template>
        <button> // second button </button>
    </ng-template>
    <ng-template>
        <button> // third button </button>
    </ng-template>
</parent_component>

Parent.component.ts

export class ParentComponent {
  @ContentChildren(TemplateRef) templateRefs: QueryList<TemplateRef>;
}

Parent.component.html

<div *ngFor="let x of templateRefs">
  <dxi-item location='after' class="osii-item-content"> 
    <ng-container *ngTemplateOutlet="x"></ng-container>
  </dxi-item>
</div>

A better solution (that isn't exactly what you asked for) would be to pass a single template for your buttons and then an array with button content. In the example I pass an array of strings, but it certainly can be whole objects.

App.component.html

<parent_component [texts]=['first', 'second', 'third'>
    <ng-template let-x @BtnTemplate>
        <button> {{x}} </button>
    </ng-template>
</parent_compnent>

Parent.component.ts

export class ParentComponent {
  @Input() texts: string[];
  @ContentChild("BtnTemplate") btnTemplateRef: TemplateRef;
}

Parent.component.html

<div *ngFor="let x of texts">
  <dxi-item location='after' class="osii-item-content"> 
    <ng-container *ngTemplateOutlet="btnTemplateRef"
                  context: { $implicit: x }">
    </ng-container>
  </dxi-item>
</div>
Janey answered 1/10, 2018 at 20:18 Comment(0)
A
0

I guess what you're looking for is something like this: <ng-container *ngFor="let item of items"> <your-compo></your-compo> </ng-container> So you iterate over the items and generates required components. Don't be worried, ng-container won't be rendered, only your components will be.

Antoninus answered 1/10, 2018 at 19:45 Comment(2)
This solution will not work as I'm getting the list of buttons from <ng-content> and are not readily available.Pasho
Kind of, I was suggesting a change in your architecture as well. But if you really need to run with ng-content you will probably be able to capture them with ViewChildren or ContentChildren and manage after parent component is able to read themAntoninus

© 2022 - 2024 — McMap. All rights reserved.