20

I'm trying to display two differents ng-content inside two ngFor loops. But as described in this answer, Angular can't project ng-content multiple times.

I tried this solution, but this does not allow me to project multiple times my content, only to display it at different places depending on an ngIf condition.

Here's my actual code :

An example parent component (any component using app-table). That's what I want to do.

<app-table [data]="myData"> <div lineHeader let-line> {{line.name}} </div> <div lineContent let-element> {{element.name}} </div> </app-table> 

The child component (app-table). Here I can do everything while the parent component keeps working the same way.

<div *ngFor="let line of data"> <ng-content select="[lineHeader]"></ng-content> <div *ngFor="let element of line"> <ng-content select="[lineContent]"></ng-content> </div> </div> 
4
  • I tried this solution That solution should help you. There is also another solution Commented Oct 27, 2017 at 13:48
  • Please recheck your code, there are multiple errors. Your property binding (select="[lineHeader]") is wrong. You need to put the square brackets around the property ([select]="lineHeader"). Commented Oct 27, 2017 at 13:51
  • @dave0688 No no no no ))) Commented Oct 27, 2017 at 13:52
  • let- is only supported on template elements and i don't get how you make for loop let line of data and then let element of line Where are you going to take line.name? Commented Oct 27, 2017 at 13:55

1 Answer 1

56

The best option in your case would be trancluding ng-template by using ngTemplateOutlet like:

<app-table [data]="myData"> <ng-template #lineHeader let-line> <div> {{line.name}} </div> </ng-template> <ng-template #lineContent let-element> <div> {{element.name}} </div> </ng-template> </app-table> 

app-table.component.ts

@Component({ selector: 'app-table', template: ` <div *ngFor="let line of data"> <ng-container *ngTemplateOutlet="lineHeaderTmpl, context: { $implicit: line }"></ng-container> <div *ngFor="let element of line.values"> <ng-container *ngTemplateOutlet="lineContentTmpl, context: { $implicit: element }"></ng-container> </div> </div> ` }) export class AppTableComponent { @Input() data: any; @ContentChild('lineHeader') lineHeaderTmpl: TemplateRef<any>; @ContentChild('lineContent') lineContentTmpl: TemplateRef<any>; } 

Stackblitz Example

Sign up to request clarification or add additional context in comments.

6 Comments

I heard about ContentChild but didn't succeed to use it efficiently. Thanks!
THIIIIISSSSSSS!
This is awesome. One thing though... is it possible to detect if ng-template exists and if it doesn't exist, then show default?
@rain01 in the above example you could just check to see if the template was found const noTemplate = !this.lineHeaderTmpl.length; and show some other content. I've had success using this method in the past: Gist
This is beautiful :')
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.