1

I'm setting up ngTemplateOutlet inside *ngFor like in below code snippet

  <ul>
    <li *ngFor="let item of list">
      <ng-container [ngTemplateOutlet]="item.type"></ng-container>
    </li>
  </ul>

Where list = [ {type: 'templateOne'}, {type: 'templateTwo'} ] and i have defined templates like below.

<ng-template #templateOne></ng-template>
<ng-template #templateTwo></ng-template>

The above template snippet is throwing error with message undermentioned

TypeError: templateRef.createEmbeddedView is not a function
    at ViewContainerRef_.push../node_modules/@angular/core/fesm5/core.js.ViewContainerRef_.createEmbeddedView (core.js:21600)
    at NgTemplateOutlet.push../node_modules/@angular/common/fesm5/common.js.NgTemplateOutlet.ngOnChanges (common.js:4026)
    at checkAndUpdateDirectiveInline (core.js:22085)

Since item.type used in ngTemplateOutlet is of type string i am suspecting it is not getting resolved to templateReference variable.

How can i convert string to a templateReference instance?

Demonstration - See this link for example and verify console for the error

4
  • Why you want convert string to template reference? Do you want to just show that string value? Commented May 6, 2019 at 9:08
  • What data do the items keep inside the list? Commented May 6, 2019 at 9:14
  • I have defined [ngTemplateOutlet]="item.type" and expecting item.type to have different names corresponding to template reference variables. Commented May 6, 2019 at 9:16
  • 1
    The most appropriate answer i received is in github link below. https://github.com/angular/angular/issues/30294#issuecomment-490393919 Commented May 17, 2019 at 7:13

3 Answers 3

1

Your question is actually how do we treat a string as a templateReferance variable in a template html. If you do not have to handle it that way, you can just try this:

 @ViewChild('templateOne') templateOne: ElementRef;
 @ViewChild('templateTwo') templateTwo: ElementRef;
  list;
  ngOnInit() {
    this.list = [ {type: this.templateOne}, {type: this.templateTwo} ];
  }
Sign up to request clarification or add additional context in comments.

1 Comment

This requires me to map the response from server and add the corresponding ElementRef to the type.
1

Here is working example:

    import { Component,ViewChild,TemplateRef,OnInit } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
  <ul>
     <li *ngFor="let item of list;let i = index">
      <ng-container [ngTemplateOutlet]="list[i].type"></ng-container>
    </li>
  </ul>
  <ng-template #templateOne>Template One</ng-template>
  <ng-template #templateTwo>Template Two</ng-template>
  `,
})
export class AppComponent  implements OnInit {
  @ViewChild('templateTwo', {read: TemplateRef}) tpl1: TemplateRef<any>;
  @ViewChild('templateOne', {read: TemplateRef}) tpl2: TemplateRef<any>;
  list;

    ngOnInit() {
      this.list=[{"type":this.tpl1},{"type":this.tpl2}];
    }

}

Reference link

Working example stackblitz

3 Comments

We will see the same error, see this example: stackblitz.com/edit/ng-template-outlet-kps7sl
This requires us to go over the response and update it with TemplateRef before we can use it in template which is overhead..
That is not possible due to type safe binding you can do [ngIf] on template and use loop by ngFor on list and match and load only ng-template not required ng-container
1

Basically, you can create pure function that does mapping/conversion:

public map(type:string, ref1:TemplateRef, ref2:TemplateRef):TemplateRef {
   switch(type) {
      case 'templateTwo':
        return ref1;
      case 'templateTwo':
        return ref2;
      default:
        return ref1;
   }
}

Template:

<ul>
    <li *ngFor="let item of list">
      <ng-container [ngTemplateOutlet]="map(item.type, templateOne, templateTwo)"></ng-container>
    </li>
</ul>

Otherwise you will need access to template context:

public map(type:string):TemplateRef {
   return (this as any)[type]; // may break in future
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.