Search code examples
angularngforng-container

How do I dynamically create html table with angular from a multidimensional array?


I'm trying to dynamically create html table from Json that has an array within it. The problem I'm running into is when trying to create the <td>s from the sub array. Below is an example of what I'm trying to accomplish.

Should I be using <ng-container *ngFor="let m of l.dArray"> ?

 myArray = [   {
        "a": "01",
        "b": "01",
        "c": "03",
        "dArray": [
            {
                "d-1": 1,
                "d-2": 2,
                "d-3": "string1"
            },
            {
                "d-1": 2,
                "d-2": 1,
                "d-3": "string2"
            },
            {
                "d-1": 3,
                "d-2": 4,
                "d-3": "string3"
            }
        ]
    }
]

Template:

<table>
<thead>
    <tr><th>A</th></tr>
    <tr><th>B</th></tr>
    <tr><th>C</th></tr>
    <tr><th>D-1</th></tr>
    <tr><th>D-2</th></tr>
    <tr><th>D-3</th></tr>
</thead>
<tbody>
    <tr *ngFor="let l of myArray">
        <td>{{l.a}}</td>
        <td>{{l.b}}</td>
        <td>{{l.c}}</td>
        <ng-container *ngFor="let m of l.dArray">
            <td>
                <div *ngIf="m.d-1 === 1; else my1Else">
                            {{ m.d-3 }}%
                          </div>
                          <ng-template #my1Else>
                            N/A
                          </ng-template>
            </td>
            <td>
                <div *ngIf="m.d-1 === 2; else my2Else">
                            {{ m.d-3 }}%
                          </div>
                          <ng-template #my2Else>
                            N/A
                          </ng-template>
            </td>
            <td>
                <div *ngIf="m.d-1 === 1; else my3Else">
                            {{ m.d-3 }}%
                          </div>
                          <ng-template #my3Else>
                            N/A
                          </ng-template>
            </td>
        </ng-container>
    </tr>
</tbody>
</table>

Expected outcome:

----------------------------
A  | B | C  | D-1         | D-2     | D-3
01 | 01| 03 | string1     | string2 | string3


actual outcome:
----------------------------
A  | B | C  

Solution

  • A few things which i did:

    1. the name of the array is dArray were 'd-1', 'd-2', 'd-3'... which had an operator as part of the name; i renamed these to d1, d2 & d3
    2. you wanted to display only one value in column 'D-1', so we do an *ngIf='i==0' to ensure that we evaluate the first row of the dArray for this table column 'D-1'
    3. we had to use a nested if and else so that only one valid value is printed, else we get a N/A

    relevant HTML:

    <table>
        <thead>
            <tr>
                <th>A</th>
                <th>B</th>
                <th>C</th>
                <th>D-1</th>
                <th>D-2</th>
                <th>D-3</th>
            </tr>
        </thead>
        <tbody>
            <tr *ngFor="let l of myArray">
                <td>{{l.a}}</td>
                <td>{{l.b}}</td>
                <td>{{l.c}}</td>
                <ng-container *ngFor="let m of l.dArray; let i=index">
                    <td *ngIf='i===0'>
                        <div *ngIf="m.d1 === 1; else my1Else1">
                            {{ m.d3 }}%
                        </div>
                        <ng-template #my1Else1>
                            <div *ngIf="m.d1 === 2; else my2Else2">
                                {{ m.d3 }}%
                            </div>
                            <ng-template #my2Else2>
                                <div *ngIf="m.d1 === 3; else my3Else3">
                                    {{ m.d3 }}%
                                </div>
                                <ng-template #my3Else3>
                                    N/A
                                </ng-template>
                            </ng-template>
                        </ng-template>
                    </td>
    
                    <td *ngIf='i===1'>
                        <div *ngIf="m.d1 === 1; else my1Else1">
                            {{ m.d3 }}%
                        </div>
                        <ng-template #my1Else1>
                            <div *ngIf="m.d1 === 2; else my2Else2">
                                {{ m.d3 }}%
                            </div>
                            <ng-template #my2Else2>
                                <div *ngIf="m.d1 === 3; else my3Else3">
                                    {{ m.d3 }}%
                                </div>
                                <ng-template #my3Else3>
                                    N/A
                                </ng-template>
                            </ng-template>
                        </ng-template>
                    </td>
    
                    <td *ngIf='i===2'>
                        <div *ngIf="m.d1 === 1; else my1Else1">
                            {{ m.d3 }}%
                        </div>
                        <ng-template #my1Else1>
                            <div *ngIf="m.d1 === 2; else my2Else2">
                                {{ m.d3 }}%
                            </div>
                            <ng-template #my2Else2>
                                <div *ngIf="m.d1 === 3; else my3Else3">
                                    {{ m.d3 }}%
                                </div>
                                <ng-template #my3Else3>
                                    N/A
                                </ng-template>
                            </ng-template>
                        </ng-template>
                    </td>
    
                </ng-container>
            </tr>
        </tbody>
    </table>
    

    you can check working stackblitz here