Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(Angular 2+) Using ng-content in *ngFor, cannot access the loop variables

How can I transclude/project into a slot that is within a loop, and have the projected content able to access the loop variables?

Say I have a base component with the following

<tr *ngFor="let data of items">
    <td>{{data.title}}</td>
    <ng-content select="[slot]"></ng-content>
</tr>

And a child component that uses the transclusion slot "slot"

<parent [items]="items"> 
    <ng-container slot>
        <td>{{data.category}}</td>
        <td>{{data.number}}</td>
    </ng-container>
</parent>

The HTML I'd like generated is

<tr>
    <td>{{data.title}}</td>
    <td>{{data.category}}</td>
    <td>{{data.number}}</td>
</tr>

But what actually happens is that "data" is not defined in the child component, which makes sense. Is there any way I can get it to work like this?

like image 858
riyuyu Avatar asked Feb 13 '17 22:02

riyuyu


1 Answers

Using TemplateRef it is possible to declare template variables acting between two components declaratively, on templates level. The following solution does not fully match your "slot" infrastructure but could be useful to further investigation.

list.component.ts

import { Component, Input, ContentChild, TemplateRef } from '@angular/core';

@Component({
  selector: 'list',
  template: `
    <tr class="box" *ngFor="let data of items">
      <td>{{data.title}}</td>
      <ng-template
        [ngTemplateOutlet]="template"
        [ngTemplateOutletContext]="{ $implicit: data }">
      </ng-template>
    </tr>`
})
export class ListComponent {
  @Input() items;
  @ContentChild(TemplateRef) template: TemplateRef;
  constructor() { }
}

wrapper.component.ts

import { Component, ContentChild, TemplateRef } from '@angular/core';

@Component({
  selector: 'wrapper',
  template: `
    <table>
      <list [items]="items">
        <ng-template let-data>
          <td>{{data.category}}</td>
          <td>{{data.number}}</td>
        </ng-template>
      </list>
    </table>`
})
export class WrapperComponent {
  items = [
    { title: 'T1', category: 'C1', number: 'N1' },
    { title: 'T2', category: 'C2', number: 'N2' },
    { title: 'T3', category: 'C3', number: 'N3' }
  ];
  @ContentChild(TemplateRef) template: TemplateRef;
  constructor() { }
}

I also created a Plunker demo...

like image 200
dhilt Avatar answered Sep 27 '22 21:09

dhilt