I'm trying to pass a different template for each field of an array of string.
TS
export class MyComponent {
  fields = ['name', 'person.age', 'created_at', ...]
}
HTML
<div *ngFor="let field of fields">
   <ng-container [ngTemplateOutlet]="field">
       
   </ng-container>
</div>
<ng-template #name>
   Name template
</ng-template>
<ng-template #created_at>
    Created at template
</ng-template>
<ng-template #person.age>
     person.age template
</ng-template>
I obviously get an error because the ngTemplateOutlet expects a TemplateRef instead of a string. But how can I pass it a string dynamically to refer to the correct template? The error I get is:
Error : templateRef.createEmbeddedView is not a function
PS: There might be better solutions for this problem. Don't hesitate to share :) Thank you!
Would you try this? (it works for me):
export class YourClass {
  @ViewChild('ciao') ciao: TemplateRef<any>;
  @ViewChild('ciao2') ciao2: TemplateRef<any>;
  
  fields: TemplateRef<any>[];
  constructor () {
    
    this.fields = [this.ciao, this.ciao2];
  }
}
<ng-template #ciao></ng-template>
<ng-template #ciao2></ng-template>
You can write it like such:
<div *ngFor="let field of fields">
   <ng-container *ngTemplateOutlet="{'name': name, 'created_at': created_at, 
     'person_age': person_age}[field]">
   </ng-container>
</div> 
<ng-template #name>
    Name template
</ng-template>
<ng-template #created_at>
    Created at template
</ng-template>
<ng-template #person_age>
     person.age template
</ng-template>
This doesn't require child component.
See comment for the workaround to pass the reference using the typescript. I just wanted to mention a second solution for those having the same problem : Use ngSwitch :)
  <div *ngFor="let field of fields">
        <div [ngSwitch]="field">
              <div *ngSwitchCase="'name'">
                   {{ field }}
              </div>
              <div *ngSwitchCase="'person.age'">
                   {{ var[field] }} is my age
              </div>
              <div *ngSwitchDefault>
                   fallback
               </div>
        </div>
                        You could create the templates in the parent component, and pass a list of templates as input to the child component :
<my-child [templates]="{'name': name, 'created_at': created_at, 'person_age': person_age}"></my-child>
<ng-template #name>
   Name template
</ng-template>
<ng-template #created_at>
    Created at template
</ng-template>
<ng-template #person_age>
     person.age template
</ng-template>
Then you can simply use the templates :
<ng-container *ngFor="let f of fields"> 
   <ng-container *ngTemplateOutlet="templates[f]">
   </ng-container>
</ng-container>
Here is a stackblitz running code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With