Angular - 在不知道结构的情况下循环显示视图组件视图上的任何 json 数据

Angular - display any json data on the view component view in a loop without knowing the structure

我有一些 json 数据需要显示在 app.component.html

这是一些示例数据:

[
  {
    "name": "d1",
    "days": [
      "monday",
      "wednesday",
    ],
    "options": {
      "name": "o1",
      "extras": [],
      "temp": [
        "12",
        "25",
        "12"
      ]
    }
  },
  {
    "name": "d2",
    "days": [
      "tuesday",
      "wednesday",
    ],
    "options": {
      "name": "o2a",
      "extras": [
        {
          name: 'extra 1'
        }
      ],
      "temp": [
        "22",
        "25",
        "12"
      ]
    }
  }
]

目前我是这样的:

<ul *ngFor="let dat of data">
  <li>{{dat.name}}</li>
</ul>

..等等

但是键的名称和值不是固定的,所以它们可以改变,或多或少。

我的问题是,在它可以读取任何 json 数据的情况下如何执行此操作?

您正在编写 <li>{{dat.name}}</li> 并期望如果密钥 name 被更改,则一切正常,但这是不可能的。

但是,如果您只想在 UI 中显示整个 JSON,您可以使用 json 管道,例如 ::

<li>{{dat | json}}</li>

如果您希望 JSON 以漂亮的打印格式显示,请更改为 ::

<div *ngFor="let dat of data">
    <pre>{{dat | json}}</pre>
</div>

就这样做吧。

<pre>
{{ data | json }}
</pre>

可能有更好的 Angular 或 JS JSON 树查看器,但这可以帮助您入门。您需要递归地遍历您的对象。

我在这里使用的是递归模板出口,你可以做组件(如果你需要添加其他功能,它可能值得研究一下)。

下面是堆栈闪电战的演示: https://stackblitz.com/edit/angular-ivy-qadvlr?file=src%2Fapp%2Fapp.component.ts

示例组件,它只是将您的数据作为一个数组,以及一个辅助方法来尝试确定我们传入的值的类型,因为它的类型将决定我们需要如何显示它。

export class AppComponent  {
  data1 = [
    {
      "name": "d1",
      "days": [
        "monday",
        "wednesday",
      ],
      "options": {
        "name": "o1",
        "extras": [],
        "temp": [
          "12",
          "25",
          "12"
        ]
      }
    },
    {
      "name": "d2",
      "days": [
        "tuesday",
        "wednesday",
      ],
      "options": {
        "name": "o2a",
        "extras": [
          {
            name: 'extra 1'
          }
        ],
        "temp": [
          "22",
          "25",
          "12"
        ]
      }
    }
  ]

  getType(val: any) {
    if (Array.isArray(val)) {// aray's will be type of "object" so need specail cases, and possibly others but this is a good start
      return 'array';
    } else if (typeof val === 'string' || val instanceof String) {
      return 'string';
    } else if (typeof val === 'boolean') {
      return 'boolean';
    } else if (typeof val === "object") {
      return 'object'
    }
  }

}

有点凌乱的递归模板,不关心 属性 名称。相反,我们使用 Angular 的 keyvalue 管道来获取对象的 keys/values。

<ul *ngFor="let someObj of data1;">
  <ng-container *ngTemplateOutlet="objectTemplate; context: {obj: someObj}"></ng-container>
</ul>


<ng-template #recursiveTemplate let-key="key" let-valueType="valueType" let-value="value">
  {{key}}

  <ng-container [ngSwitch]="valueType">

      <ng-container *ngSwitchCase="'array'">
        <ng-container *ngTemplateOutlet="arrayTemplate; context: { value: value}"></ng-container>
      </ng-container>

      <ng-container *ngSwitchCase="'object'">
        <ul>
        <ng-container *ngTemplateOutlet="objectTemplate; context: {obj: value}"></ng-container>
        </ul>
      </ng-container>

      <!-- anything we might have missed or don't needs anything special for, just show it as JSON -->
      <ng-container *ngSwitchDefault>
         {{key ? "- " : ""}}{{value | json}}
      </ng-container>

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

<ng-template #arrayTemplate let-value="value">
  <ul>
    <li *ngFor="let child of value;">
        <ng-container *ngTemplateOutlet="recursiveTemplate; context:{ key:null, valueType: getType(child), value: child }"></ng-container>
    </li>
  </ul>
</ng-template>

<ng-template #objectTemplate let-obj="obj">
  <li *ngFor="let item of obj | keyvalue;">
  <ng-container *ngTemplateOutlet="recursiveTemplate; context:{ key:item.key, valueType: getType(item.value), value: item.value }"></ng-container>
  </li>
</ng-template>