如何使用基于对象的 ngFor 动态加载多个 ng 模板 属性

How to load multiple ng-templates dynamically with ngFor based on object property

[第一步] 我有一个对象 "article",它有一个包含多个内容元素的数组。根据元素的类型(例如 header/image),应显示不同的模板。如果没有必要,我不想为此明确拥有自己的组件,所以我猜测是否需要 ViewChild 或 ContentChild?

我已经调查了所有与 ngTemplate 相关的问题,但还没有找到解决方案。 我试图重写 https://stackblitz.com/edit/angular-q1y2vz 来自 ,但到目前为止失败了。

component.ts

articles: any[] = [ {
    "id_seq": "1234",
    "content":[
      {
        "id": "123456",
        "order": 0,
        "type": "header",
        "data":
          {
            "text": "loremipsum"
          }
      },
      {
        "id": "234567",
        "order": 1,
        "type": "image",
        "data":
          {
            "url": "http://www.google.de/image.jpg"
          }
      }]
  }]

component.html

<ng-container *ngFor="let content of articles[0]?.content;">
  <ng-container [ngTemplateOutlet]="content?.type">
  </ng-container>
</ng-container>


<ng-template #header >
  <p>I'm a header</p>
</ng-template>

<ng-template #image >
  <p>I'm an image</p>
</ng-template>

根据 ngTemplateOutlet 的语法和代码放置,我收到错误

templateRef.createEmbeddedView is not a function

或者什么都不渲染。

如果我输入像 "header" 这样的静态字符串,它就可以工作。所以我猜,content?.type 不是要走的路。 另一方面,像这样的东西工作正常:

<accordion>
  <accordion-group heading="articlecontent" [isOpen]="isFirstOpen">
    <div class="accordion_no_side_margin">
      <accordion-group *ngFor="let content of articles[0]?.content"
                       [heading]="content?.type">
        {{ content?.id }}
        {{ content?.order }}
        {{ content?.type }}
        {{ content?.data }}
      </accordion-group>
    </div>
  </accordion-group>
</accordion>

[第二步] 最终我确实想合并这两个代码片段,以便 ng-template 应该在手风琴内部执行。

[第三步] 稍后我打算添加 ngTemplateOutletContext 并提供一些信息,但如果没有它,其他步骤应该也能正常工作。

目前我正在使用 @angular-devkit/core 8.1.3

不知道你的代码中的 articles[0]?.content 是什么意思,但可以这样尝试:

<ng-container *ngFor="let content of articles[0]?.content;">
    <ng-container *ngIf="content?.type == header; then header; else image"></ng-container>
    <ng-template #header >
      <p>I'm a header</p>
    </ng-template>

    <ng-template #image >
      <p>I'm an image</p>
    </ng-template>
  </ng-container>

如果上述方法不起作用,请尝试这样您的数组未加载:

<div *ngIf="articles | async as artic">
  <ng-container *ngFor="let article of artic">
    <ng-container *ngfor="let ar of article.content">

      <ng-container *ngIf="ar.type == header; then header; else image"></ng-container>
      <ng-template #header>
        <p>I'm a header</p>
      </ng-template>

      <ng-template #image>
        <p>I'm an image</p>
      </ng-template>
    </ng-container>
  </ng-container>
</div>

如果您有硬编码数组,您可以删除 | async 管道。

对你在评论中告诉我的话发誓:

<div *ngIf="articles | async as artic">
  <ng-container *ngFor="let article of artic">
    <ng-container *ngfor="let ar of article.content">

      <ng-container *ngIf="ar.type == 'header'"><p>I'm a header</p></ng-container>
      <ng-container *ngIf="ar.type == 'image'"><p>I'm a header</p></ng-container>
      <ng-container *ngIf="ar.type == 'pain in ass'"><p>I'm a header</p></ng-container>
      <ng-container *ngIf="ar.type == 'love masturbating'"><p>I'm a header</p></ng-container>
      <ng-container *ngIf="ar.type == 'love dogs'"><p>I'm a header</p></ng-container>

    </ng-container>
  </ng-container>
</div>

由于它出于某种原因不想与 ngFor 一起工作,我尝试了 ngSwitchCase,它工作得很好,从那以后就再也没有回头 (虽然在外面有 templates/ng-containers 会很好)

<ng-container *ngFor="let content of localArticles[0]?.content">
  <ng-container [ngSwitch]="content?.type">

    <ng-container *ngSwitchCase="'header'">
      <p>I'm a header</p>
    </ng-container>

    <ng-container *ngSwitchCase="'image'">
      <p>I'm an image</p>
    </ng-container>

  </ng-container>
</ng-container>