javascriptangulartransclusion

Custom template(transclusion without ng-content) for list component in Angular2


I have a list component which shows only names. list component should be able to take custom template which will be given by user.

List Component

import {Component } from 'angular2/core';

@Component({
  selector: 'my-list',
  template: `<p>This is List</p>
     <ul>
       <li *ngFor="#i of data"><div class='listItem'>{{i.name}}</div></li>
    </ul>`
})
export class MyList implements OnInit{ 
    data: Array<any> = [{name: 'John', age: 26},{name: 'Kevin', age: 26},  {name:'Simmons', age:26}];
}

My Requirement

<my-list>
   <div>{{i.name}}-{{i.age}}</div> //user should be able to provide custom template like this
</my-list>

I tried this with ng-content but it throws error. In angular 1 same thing used to work with transcluded content. do we have any alternative of manual transclusion in angular 2 and if not then how could we implement this feature in angular2.

Here is Plunker


Solution

  • You need to use ngForTemplate, I've created PrimeNG DataList and many other DataComponents using this technique and it works great. Demo;

    http://www.primefaces.org/primeng/#/datalist

    Code;

    https://github.com/primefaces/primeng/blob/master/src/app/components/datalist/datalist.ts

    In your component, define a templateRef with contentchild;

    @ContentChild(TemplateRef) itemTemplate: TemplateRef;
    

    Your template becomes;

    template: `<p>This is List</p>
         <ul>
           <template ngFor [ngForOf]="data" [ngForTemplate]="itemTemplate"></template>
        </ul>`
    

    So that your users can define content like;

    <my-list>
       <template #anything>
            <div>{{anything.i.name}}-{{anything.i.age}}</div>
       </template>
    </my-list>