Search code examples
angulartemplatescomponents

Component with ngFor that accept template and pass it to the children, how to do it?


i'm developing an Angular 6 app. I have a component BelloComponent that render a list passed on @Input items.

@Component({
  selector: 'bello',
  template: `
    <ul *ngIf="items?.length">
      <li *ngFor="let item of items">
        ???
      </li>
    </ul>
`
})
export class BelloComponent {
  @Input() items: Array<Object>;
}

And the consumer, AppComponent uses BelloComponent. How to render the list pasisng it from AppComponent a template inside the BelloComponent tag?

@Component({
  selector: 'my-app',
  template: `
<bello [items]="cacche_list">
  <b>{{ name }}, puzza value: {{ puzza }}</b>
</bello>`
})
export class AppComponent  {

  cacche_list = [
    { name: 'cacca 1', puzza: 3 },
    { name: 'cacca 2', puzza: 5 },
    { name: 'cacca 3', puzza: 66 },
    { name: 'cacca 4', puzza: 5 },
    { name: 'cacca 5', puzza: 2 },
    { name: 'cacca 6', puzza: 12 },
  ];
}

The stackblitz is this: https://stackblitz.com/edit/angular-exbhsv?file=src%2Fapp%2Fapp.component.ts

I think i'm missing something, how to tell to BelloComponent how to render the element in the ngFor? How to have access to the single item rendered from AppComponent?


Solution

  • Using transclusion you can deal with it this way

    @Component({
     selector: 'bello',
     template: `
        <ul *ngIf="items?.length">
         <li *ngFor="let item of items">
           <ng-container *ngTemplateOutlet="liTemplate; context: { $implicit: item}"></ng-container>
         </li>
       </ul>
     `
    })
    export class BelloComponent {
      @ContentChild(TemplateRef) liTemplate: TemplateRef<any>;
      @Input() items: Array<Object>;
    }
    

    and in your container component

    @Component({
      selector: 'my-app',
      template: `
    <bello [items]="cacche_list">
      <ng-template let-item>
         <b>{{ item.name }}, puzza value: {{ item.puzza }}</b>
      </ng-template>
    </bello>`
    })
    export class AppComponent  {
    
      cacche_list = [
        { name: 'cacca 1', puzza: 3 },
        { name: 'cacca 2', puzza: 5 },
        { name: 'cacca 3', puzza: 66 },
        { name: 'cacca 4', puzza: 5 },
        { name: 'cacca 5', puzza: 2 },
        { name: 'cacca 6', puzza: 12 },
      ];
    }
    

    For further informations see this blog https://www.kaels-kabbage.com/post/angular-transclusion-with-parameters/