Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 : Pass string to ngTemplateOutlet

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!

like image 494
Shrakka Avatar asked Apr 23 '18 07:04

Shrakka


4 Answers

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>
like image 32
Luca Taccagni Avatar answered Nov 04 '22 21:11

Luca Taccagni


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.

like image 81
Razif Baital Avatar answered Nov 04 '22 22:11

Razif Baital


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>
like image 33
Shrakka Avatar answered Nov 04 '22 21:11

Shrakka


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.

like image 4
ibenjelloun Avatar answered Nov 04 '22 21:11

ibenjelloun