Home > Back-end >  Nested object with *ngFor
Nested object with *ngFor

Time:09-22

Am trying to create a list using mat-list with below Json structure

{
    "Parent1": [
        {
            "Data1": [
                "child1",
                "child2"
            ]
        }
    ],
    "Parent2": [
        {
            "Data2": [
                "child3",
                "child4"
            ]
        }
    ]
}

Html Code

<mat-list >
       <ng-container *ngFor="let item of (jsonData | keyvalue) ;">
         <mat-list-item>
           <h3 matLine> {{item.key}}</h3>

           <mat-icon>close</mat-icon>
           <div >
             <mat-divider></mat-divider>
           </div>
         </mat-list-item>
         <ng-container *ngFor="let child of (item |keyvalue) ;">
           <mat-list-item *ngFor="let subChild of (child |keyvalue) ;">
             {{subChild.value}}
             <mat-icon>close</mat-icon>
           </mat-list-item>
<mat-list>

On the first page load it showing values like below.I need to avoid those values

enter image description here

I need to create a list like below based on the above Json enter image description here

Note: Am not sure it is the right way to iterate the object It will appreciate some one give solution.

Thanks in advance.

CodePudding user response:

Solution 1: With $any()

A cheating way by using $any() type cast function to prevent type checking.

<mat-list>
  <ng-container *ngFor="let item of jsonData | keyvalue">
    <mat-list-item>
      <h3 matLine>{{ item.key }}</h3>

      <mat-icon>close</mat-icon>
      <div >
        <mat-divider></mat-divider>
      </div>
    </mat-list-item>

    <ng-container *ngFor="let child of $any(item.value)">
      <ng-container *ngFor="let subChild of child | keyvalue">
        <ng-container *ngFor="let value of $any(subChild.value)">
          <mat-list-item>
            {{ value }}
            <mat-icon>close</mat-icon>
          </mat-list-item>
        </ng-container>
      </ng-container>
    </ng-container>
  </ng-container>
</mat-list>

Solution 2: Restructure the JSON Data

From my perspective, the data that you want to represent in the HTML is something like:

{
  Parent1: ["child1", "child2"],
  Parent2: ["child3", "child4"],
}

Hence, you can work with Object.keys() or Object.entries() (require es2017) to iterate key-value pair and with .reduce() to transform your input data to representation data.

formattedJsonData = {};

this.formattedJsonData = Object.keys(this.jsonData).reduce((acc, cur) => {
      acc[cur] = [];

      for (let item of this.jsonData[cur]) {
        for (let prop in item) {
          for (let value of item[prop]) acc[cur].push(value);
        }
      }

      return acc;
    }, {});
<mat-list>
  <ng-container *ngFor="let item of formattedJsonData | keyvalue">
    <mat-list-item>
      <h3 matLine>{{ item.key }}</h3>

      <mat-icon>close</mat-icon>
      <div >
        <mat-divider></mat-divider>
      </div>
    </mat-list-item>

    <ng-container *ngFor="let child of item.value">
      <mat-list-item>
        {{ child }}
        <mat-icon>close</mat-icon>
      </mat-list-item>
    </ng-container>
  </ng-container>
</mat-list>

Demo Solution 1 & 2 @ StackBlitz

  • Related