Here's a component which will display any data, including scalar, nested objects and arrays etc.
expand-json.component.html
<div class="json-container">
<ul class="json-list">
<ng-container *ngIf="isScalar(jsonData); else complex"> <!-- only invoked if the component is passed a scalar, never happens on recursion -->
{{jsonData}}
</ng-container>
<ng-template #complex>
<ng-container *ngIf="isArray(jsonData); else notArray">
<li *ngFor="let item of jsonData;let i=index;">
<span *ngIf="!isNull(item) && jsonData.length > 0 && !isScalar(item)" class="toggle" (click)="toggleExpand('index' + i)">
<i class="fa" [ngClass]="{'fa-caret-right': !expanded['index'+i], 'fa-caret-down': expanded['index'+i]}" ></i>
</span>
{{ i }}: {{isScalar(item) ? item : ""}}
<ul class="nested-json-list" *ngIf="expanded['index' + i]">
<app-expandable-json [jsonData]="item"></app-expandable-json>
</ul>
</li>
</ng-container>
<ng-template #notArray>
<li *ngFor="let item of objectKeys(jsonData)">
<span *ngIf="!isNull(jsonData[item]) && ( !isArray(jsonData[item]) || jsonData[item].length > 0) && !isScalar(jsonData[item]);" class="toggle" (click)="toggleExpand(item)">
<i class="fa" [ngClass]="{'fa-caret-right':!expanded[item], 'fa-caret-down':expanded[item]}"></i>
</span>
{{ item }}: {{isScalar(jsonData[item]) ? jsonData[item] : ""}}
<ul class="nested-json-list" *ngIf="expanded[item]">
<app-expandable-json [jsonData]="jsonData[item]"></app-expandable-json>
</ul>
</li>
</ng-template>
</ng-template>
</ul>
</div>
expand-json.component.css
.json-container {
font-family: monospace;
font-size: 14px;
}
.json-list {
list-style-type: none;
padding-left: 1em;
}
.nested-json-list {
list-style-type: none;
padding-left: 1em;
}
.toggle {
cursor: pointer;
margin-right: 5px;
}
expand-json.component.ts
import { Component, Input } from '@angular/core';
import {NgClass, NgForOf, NgIf} from "@angular/common";
@Component({
selector: 'app-expandable-json',
styleUrls: ['./expand-json.component.scss'],
templateUrl: 'expand-json.component.html',
standalone: true,
imports: [
NgForOf,
NgClass,
NgIf
],
})
export class ExpandableJsonComponent {
@Input() jsonData: any;
expanded: { [key: string]: boolean } = {};
objectKeys(obj: any): string[] {
return Object.keys(obj);
}
isObject(val: any): boolean {
return val != null && typeof val === 'object' && Array.isArray(val) === false;
}
isArray( val: any): boolean {
return val != null && Array.isArray(val) === true;
}
isScalar( val: any): boolean {
return val === null || ( Array.isArray(val) === false && ! this.isObject(val));
}
isNull(val: any): boolean {
return val === null;
}
toggleExpand(key: string): void {
this.expanded[key] = !this.expanded[key];
}
}
Include the component in the module:
import {ExpandableJsonComponent} from ".../expand-json.component";
@NgModule({
imports: [
ExpandableJsonComponent
],
Use it like this:
<app-expandable-json [jsonData]="data"></app-expandable-json>