angular 5: templateRef.createEmbeddedView is not a function

Viewed 47976

Here's the code I'm trying to get to work (angular 5):

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

@Component({
  selector: 'vcr',
  template: `
    <template #tpl>
      <h1>ViewContainerRef</h1>
    </template>
    <div>Some element</div>
    <div #container></div>
  `,
})
export class VcrCmp {
  @ViewChild('container', { read: ViewContainerRef }) _vcr;
  @ViewChild('tpl') tpl: TemplateRef<any>;

  constructor(
    private viewContainerRef: ViewContainerRef
  ) {

  }

  ngAfterViewInit() {
    console.info(this.viewContainerRef);
    console.info(this._vcr);

    this._vcr.createEmbeddedView(this.tpl);
    this.viewContainerRef.createEmbeddedView(this.tpl);
  }
}

The problem is that I've got this (templateRef.createEmbeddedView is not a function) error and don't really understand why.

This code is based on this example https://netbasal.com/angular-2-understanding-viewcontainerref-acc183f3b682 so I guess it should work.

What am I doing wrong?

7 Answers

According to angular 5 changelog:

The compiler option enableLegacyTemplate is now disabled by default as the element was deprecated since v4. Use <ng-template> instead.

So you should use ng-template instead of template:

<ng-template #tpl>
   <h1>ViewContainerRef</h1>
</ng-template>

Stackblitz Example

or set enableLegacyTemplate to true:

platformBrowserDynamic().bootstrapModule(AppModule, { enableLegacyTemplate: true })

Stackblitz Example

But you should know that

The option enableLegacyTemplate and the <template> element will both be removed in Angular v6.

In my case the error was due to me forgetting * (asterisk) before ngTemplateOutlet

When you reference in the *ngIf, else clause can’t be any arbitrary component, but it must be a ng-template.

For eg,

in a component where you have a source code similar to this:

<div *ngIf="myCondition ; else elseSection">
    <!-- ... -->
</div>
<div #elseSection>
    <!-- ... -->
</div>

The resulting source code should look like this:

<div *ngIf="myCondition ; else elseSection">
    <!-- ... -->
</div>
<ng-template #elseSection>
    <!-- ... -->
</ng-template>

ref : https://techoverflow.net/2018/02/17/how-to-fix-angular-typeerror-templateref-createembeddedview-is-not-a-function/

For me, the problem was using the same name for a variable in the component, and for a template in the HTML file.

Seems obvious, but I missed this.

In newer version(Angular 8+) this error is thrown if you're not passing the template when template was expected by Angular.

<ng-container *ngIf="getTemplate(col) as template; else defaultColumn">
  <ng-container *ngTemplateOutlet="template; context: {'cell': rowData[col.field]}"></ng-container>
</ng-container>
<ng-template #defaultColumn>
  {{rowData[col.field]}}
</ng-template>

In above case your getTemplate method should return actual template or null, nothing else. I was returning Directive Class here. Hence the error.

In my case the error was due to me typed [ngTemplateOutlet] instead of [ngTemplateOutletContext]

then [ngTemplateOutlet] appeared twice and caused the error.

In my case I was trying to lazy load a component using import statement and *ngComponentOutlet but instead of *ngComponentOutlet I used *ngTemplateOutlet.

Once I fixed this it worked like a charm.

Related