angular 5: templateRef.createEmbeddedView 不是函数

angular 5: templateRef.createEmbeddedView is not a function

这是我尝试开始工作的代码 (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);
  }
}

问题是我遇到了这个 (templateRef.createEmbeddedView is not a function) 错误,我不太明白为什么。

此代码基于此示例https://netbasal.com/angular-2-understanding-viewcontainerref-acc183f3b682,所以我想它应该可以工作。

我做错了什么?

根据 angular 5 更新日志:

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

所以你应该使用 ng-template 而不是 template:

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

Stackblitz Example

或将enableLegacyTemplate设置为true:

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

Stackblitz Example

但你应该知道

选项 enableLegacyTemplate 和 <template> 元素都将在 Angular v6.

中删除

在*ngIf中引用时,else子句不能是任意组件,但必须是ng-template。

例如,

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>

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

在我的例子中,错误是由于我在 ngTemplateOutlet

之前忘记了 *(星号)

对我来说,问题在于组件中的变量和 HTML 文件中的模板使用了相同的名称。

看起来很明显,但我错过了这一点。

在较新的版本(Angular 8+)中,如果您在 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>

在上述情况下,您的 getTemplate 方法应该 return 实际模板或 null,没有别的。我在这里 returning 指令 ​​Class。因此错误。

在我的例子中,错误是由于我输入了 [ngTemplateOutlet] 而不是 [ngTemplateOutletContext]

然后 [ngTemplateOutlet] 出现了两次并导致错误。

在我的例子中,我尝试使用 import 语句和 *ngComponentOutlet 延迟加载组件,但我使用 *ngTemplateOutlet.

而不是 *ngComponentOutlet

一旦我解决了这个问题,它就像一个魅力。