Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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!

like image 679
Scott Avatar asked Oct 01 '18 19:10

Scott


People also ask

How do you style content that was projected using NG-content?

If you want to style the projected content within <ng-content>, you can do so using :host and ::ng-deep to apply styling to all nested elements within the <contact> component.

What is Contentprojection?

Content projection is a pattern in which you insert, or project, the content you want to use inside another component. For example, you could have a Card component that accepts content provided by another component.

How do you use Ngcontent?

The ng-content is used when we want to insert the content dynamically inside the component that helps to increase component reusability. Using ng-content we can pass content inside the component selector and when angular parses that content that appears at the place of ng-content.

What is the difference between Ng-content and ng template?

ng-container serves as a container for elements which can also accept structural directives but is not rendered to the DOM, while ng-template allows you to create template content that is not rendered until you specifically (conditionally or directly) add it to the DOM.


1 Answers

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>
like image 110
Daniel Gimenez Avatar answered Sep 26 '22 10:09

Daniel Gimenez