4

I am trying to display a nested json array into my material angular table. My data works fine if my json does not have nested arrays.

Json

{
"rows": [
    {
        "mst": {
            "field": "createDate",
            "value": "2017-06-02"
        },
        "gsc": {
            "field": "Account/Audit/Creation/Date",
            "value": "2017-06-02"
        }
    },
    {
        "mst": {
            "field": "startDate"
        },
        "gsc": {
            "field": "startDate"
        }
    },
    {
        "mst": {
            "field": "status",
            "value": "ACTIVE"
        },
        "gscs": [
            {
                "field": "Account/LineOfBusiness/Type~Status",
                "value": "C~A"
            },
            {
                "field": "Account/LineOfBusiness/Type~Status",
                "value": "I~A"
            }                
        ],
        "gscvalue": "Active"
    },
    {
        "mst": {
            "field": "statusDate"
        },
        "gsc": {
            "field": "statusDate"
        }
    },
    {
        "mst": {
            "field": "statusReason"
        },
        "gsc": {
            "field": "statusReason"
        }
    },
    {
        "mst": {
            "field": "deliveryMethod",
            "value": "PAPER"
        },
        "gscs": [
            {
                "field": "Electronic",
                "value": "N"
            },
            {
                "field": "ElectronicOutsourced",
                "value": "N"
            },
            {
                "field": "Hardcopy",
                "value": "Y"
            }
        ],
        "gscvalue": "Paper"
    },
    {
        "mst": {
            "field": "statementFormat",
            "value": "Standard"
        },
        "gsc": {
            "field": "?"
        }
    },
    {
        "mst": {
            "field": "statementLanguagePreference",
            "value": "Spanish"
        },
        "gsc": {
            "field": "Account/Language",
            "value": "S"
        },
        "gscvalue": "Spanish"
    },
    {
        "mst": {
            "field": "type",
            "value": "RES"
        },
        "gsc": {
            "field": "Account/Type",
            "value": "RES"
        }
    }
]
}

HTML

<div class="example-container mat-elevation-z8" *ngIf="rows?.length>0">
<table mat-table [dataSource]="dataSource">

<ng-container matColumnDef="mst Fields">
  <th mat-header-cell *matHeaderCellDef> mst Fields </th>
  <td mat-cell *matCellDef="let row" class="tablePadding"> {{row.mst.field}} </td>
</ng-container>

<ng-container matColumnDef="mst">
  <th mat-header-cell *matHeaderCellDef> mst value </th>
  <td mat-cell *matCellDef="let row"> {{row.mst.value}} </td>
</ng-container>

<ng-container matColumnDef="gsc Fields">
  <th mat-header-cell *matHeaderCellDef> gsc Fields </th>
  <td mat-cell *matCellDef="let row"> {{row.gsc.field}} </td>
</ng-container>

<ng-container matColumnDef="gsc">
  <th mat-header-cell *matHeaderCellDef> gsc value </th>
  <td mat-cell *matCellDef="let row"> {{row.gsc.value}} </td>           
</ng-container>

<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns; let row"></tr>

modal.ts

export class ResultField {
field: string;
value: string;
valueList: string[];
}

export class ResultRow {
mst: ResultField;
gsc: ResultField;
gscs: ResultField[];
gscValue: String;
}

My current table will display data all the way up until it reaches mst.field{status}. I get an error

SystemComponent.html:29 ERROR TypeError: Cannot read property 'field' of undefined

I understand this error is coming because of my current logic in my html. How can I resolve this?

Hence, I don't want gscs.field in a separate column I want those values into gsc.field column and the gscValue in the gsc.value column.

Attempt

<ng-container matColumnDef="gsc Fields">
  <th mat-header-cell *matHeaderCellDef> gsc Fields </th>
  <td mat-cell *matCellDef="let row" *ngIf="row.gsc.field"> {{row.gsc.field}} </td>
<td mat-cell *matCellDef="let row" *ngIf="row.gsc.field"> {{row.gscs.field}} </td>
</ng-container>

But with angular logic there can only be one * directives in a tag.

My closest reference is Need to display Nested JSON Object in Material Data Table but there were no solid answers.

Attempt 2

I tried using a simpler approach just to get my data printed.

<div>
  <h1>Testing</h1>

  <div *ngFor="let row of rows">
    <!-- <p *ngIf="row.gsc.field">{{row.gsc.field}}</p>
    <p *ngIf="row.gsc.value">{{row.gsc.value}}</p> -->
    <p>{{row.mst.field}}</p>
    <p>{{row.mst.value}}</p>   


  <div *ngFor= "let gscs of row.gscs">
    <p *ngIf="gscs.field">{{gscs.field}}</p>
    <p *ngIf="gscs.value">{{gscs.value}}</p>
</div>
<p *ngIf = "row.gscvalue">{{row.gscvalue}}</p>
  </div>  
</div>

With this code snippet, I am able to pull the nested values however I am getting the same error as above when I uncomment these two lines.

<!-- <p *ngIf="row.gsc.field">{{row.gsc.field}}</p>
<p *ngIf="row.gsc.value">{{row.gsc.value}}</p> -->

ERROR TypeError: Cannot read property 'field' of undefined

With the JSON I provided above, I want to create a table that looks like this following picture.

Final Output

2
  • so when there's an array, you want multiple cells to represent that? Commented Apr 13, 2020 at 16:34
  • @bryan60 Yes. That's correct. It can be gscs.field only if we cannot set gscs.field and gscs.value in the same cell. Commented Apr 13, 2020 at 16:36

1 Answer 1

3
+50

seems like you just need to nest your ngIf:

<ng-container matColumnDef="gsc Fields">
  <th mat-header-cell *matHeaderCellDef> gsc Fields </th>
  <td mat-cell *matCellDef="let row">
    <ng-container *ngIf="row.gsc?.field; else fieldArray">
      {{row.gsc.field}} 
    </ng-container>
    <ng-template #fieldArray>
      <div class="sub-cell" *ngFor="let field of row.gscs"> <!-- need the appropriate css -->
        {{field.field}} {{field.value}}
      </div>
    </ng-template>
  </td>
</ng-container>

and in your value column you want more like:

<ng-container matColumnDef="gsc">
  <th mat-header-cell *matHeaderCellDef> gsc value </th>
  <td mat-cell *matCellDef="let row"> {{row.gsc?.value || row.gscvalue}} </td>           
</ng-container>

not sure this is 100% but should be close

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you Bryan! You are a life savior! This helped a lot. Will provide you the bounty once the timer is up.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.