0

i am trying to create template reference through ngFor loop. but not works.

ts file:

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  members = [
    {
      name: 'name1',
      id:"one"
    },
    {
      name: 'name2',
      id:"two"
    },
    {
      name: 'name3',
      id:"three"
    } 
  ]
}

template:

<div class="container">
  <h2>Test popover</h2>
  <p>
    How to declare a dynamic template reference variable inside a ngFor element?
  </p>
</div>

<div *ngFor="let member of members">
  <ng-container [ngTemplateOutlet]="{{member.id}}"
    >Hello, <b>{{ member.name }}</b
    >!</ng-container
  >
</div>

<ng-template #one> one </ng-template>
<ng-template #two> two </ng-template>
<ng-template #three> three </ng-template>

Live demo

I am getting an error as:

Type '{ "": any; }' is not assignable to type 'TemplateRef<any>'. Object literal may only specify known properties, and '""' does not exist in type 'TemplateRef<any>'.

3gwebtrain
  • 14,640
  • 25
  • 121
  • 247

1 Answers1

1

Update:

If you want to pass ngTemplate to child, you can use contentChild

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

@Component({
  selector: 'hello',
  template: `
  <div *ngFor="let member of members">
      {{member.name}} <ng-container [ngTemplateOutlet]="this[member.id]"></ng-container>
  </div>
  `,
  styles: [`h1 { font-family: Lato; }`],
})
export class HelloComponent {
  @ContentChild('one') one: TemplateRef<any>;
  @ContentChild('two') two: TemplateRef<any>;
  @ContentChild('three') three: TemplateRef<any>;
  @Input() members: any;
}

forked stackblitz

Solution1:

Instead of hardcoding the template names, you can just render based on the index

<div class="container">
  <h2>Test popover</h2>
  <p>
    How to declare a dynamic template reference variable inside a ngFor element?
  </p>
</div>
<div *ngFor="let member of members; let i = index">
  <ng-container *ngIf="temps">
    <ng-container [ngTemplateOutlet]="temps.toArray()[i]"
      >Hello, <b>{{ member.name }}</b
      >!</ng-container
    ></ng-container
  >
</div>

<ng-template #temp> one </ng-template>
<ng-template #temp> two </ng-template>
<ng-template #temp> three </ng-template>

forked stackblitz

Solution2:

You can chain ternary conditions so that you get the output as required

<div class="container">
  <h2>Test popover</h2>
  <p>
    How to declare a dynamic template reference variable inside a ngFor element?
  </p>
</div>

<div *ngFor="let member of members">
  <ng-container
    *ngTemplateOutlet="
      member.id === 'one' ? one : member.id === 'two' ? two : three
    "
    >Hello, <b>{{ member.name }}</b
    >!</ng-container
  >
</div>

<ng-template #one> one </ng-template>
<ng-template #two> two </ng-template>
<ng-template #three> three </ng-template>

forked stackblitz

Naren Murali
  • 19,250
  • 3
  • 27
  • 54
  • I am getting an error as `Type 'string' is not assignable to type 'TemplateRef'.` when i nest with child element. idea is need to pass ref from parent to child. can you check here: https://stackblitz.com/edit/angular-ivy-xaky9a?file=src/app/hello.component.ts – 3gwebtrain Sep 08 '22 at 02:47
  • @3gwebtrain that was not a part of the question? – Naren Murali Sep 08 '22 at 02:48
  • I do required to add the template from parent to child. is there any way? – 3gwebtrain Sep 08 '22 at 03:08
  • @3gwebtrain you need to do `@input` check this [answer](https://stackoverflow.com/questions/51971873/insert-a-template-to-child-component-in-angular-6) Also this [answer](https://stackoverflow.com/questions/48853014/angular-5-pass-ng-template-down-to-child-component-using-ngtemplateoutlet) – Naren Murali Sep 08 '22 at 04:09
  • @3gwebtrain updated my answer! – Naren Murali Sep 08 '22 at 04:15