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>
我有一些 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>