Home > Blockchain >  How can I fill a table vertically in Angular?
How can I fill a table vertically in Angular?

Time:08-12

I want to show in the frontend the Mitre matrix in a table, but the backend response contains more data, like how many tickets have been classified in each tactic. So I want to fill the table vertically column by column instead of row by row. The backend response:

"tableData": [
            {
                "technique": "Reconnaissance",
                "tactics": [
                    {
                        "tactic": "Active Scanning",
                        "id": "T1595",
                        "total_tickets": 14
                    },
                    {
                        "tactic": "Gather Victim Host Information",
                        "id": "T1592",
                        "total_tickets": 0
                    },
                    {
                        "tactic": "Gather Victim Identity Information",
                        "id": "T1589",
                        "total_tickets": 0
                    },
                    {
                        "tactic": "Gather Victim Network Information",
                        "id": "T1590",
                        "total_tickets": 0
                    },
                    {
                        "tactic": "Gather Victim Org Information",
                        "id": "T1591",
                        "total_tickets": 2
                    },
                    {
                        "tactic": "Phishing for Information",
                        "id": "T1598",
                        "total_tickets": 1
                    },
                    {
                        "tactic": "Search Closed Sources",
                        "id": "T1597",
                        "total_tickets": 0
                    },
                    {
                        "tactic": "Search Open Technical Databases",
                        "id": "T1596",
                        "total_tickets": 0
                    },
                    {
                        "tactic": "Search Open Websites/Domains",
                        "id": "T1593",
                        "total_tickets": 0
                    },
                    {
                        "tactic": "Search Victim-Owned Websites",
                        "id": "T1594",
                        "total_tickets": 1
                    }
                ]
            },
            {
                "technique": "Resource Development",
                "tactics": [
                    {
                        "tactic": "Acquire Infrastructure",
                        "id": "T1583",
                        "total_tickets": 1
                    },
                    {
                        "tactic": "Compromise Accounts",
                        "id": "T1586",
                        "total_tickets": 1
                    },
                    {
                        "tactic": "Compromise Infrastructure",
                        "id": "T1584",
                        "total_tickets": 5
                    },
                    {
                        "tactic": "Develop Capabilities",
                        "id": "T1587",
                        "total_tickets": 4
                    },
                    {
                        "tactic": "Establish Accounts",
                        "id": "T1585",
                        "total_tickets": 0
                    },
                    {
                        "tactic": "Obtain Capabilities",
                        "id": "T1588",
                        "total_tickets": 2
                    },
                    {
                        "tactic": "Stage Capabilities",
                        "id": "T1608",
                        "total_tickets": 0
                    }
                ]
            },
            {
                "technique": "Initial Access",
                "tactics": [
                    {
                        "tactic": "Drive-by Compromise",
                        "id": "T1189",
                        "total_tickets": 1
                    },
                    {
                        "tactic": "Exploit Public-Facing Application",
                        "id": "T1190",
                        "total_tickets": 2
                    },
                    {
                        "tactic": "External Remote Services",
                        "id": "T1133",
                        "total_tickets": 0
                    },
                    {
                        "tactic": "Hardware Additions",
                        "id": "T1200",
                        "total_tickets": 0
                    },
                    {
                        "tactic": "Phishing",
                        "id": "T1566",
                        "total_tickets": 2
                    },
                    {
                        "tactic": "Replication Through Removable Media",
                        "id": "T1091",
                        "total_tickets": 1
                    },
                    {
                        "tactic": "Supply Chain Compromise",
                        "id": "T1195",
                        "total_tickets": 0
                    },
                    {
                        "tactic": "Trusted Relationship",
                        "id": "T1199",
                        "total_tickets": 0
                    },
                    {
                        "tactic": "Valid Accounts",
                        "id": "T1078",
                        "total_tickets": 8
                    }
                ]
            }
       ]

The HTML of the table, but the following code just filled a single column, but I want that after filled the first column with the firts technique the remaining data will be in the others columns (btw I'm using the NG Zorro library).

<div >
  <div >
    <div >
      <span *ngIf="isLoading">Cargando...</span>
      <span *ngIf="!isLoading">{{totalData || 0}} {{title || ''}}</span>
    </div>
  </div>

  <div >
    <nz-table #basicTable
              [nzShowPagination]="false"
              [nzTotal]="totalData"
              [nzLoading]="isLoading"
              [nzBordered]="true"
              [nzData]="data">
      <thead>
        <tr>
          <th *ngFor="let technique of basicTable.data">{{technique.technique}}</th>
        </tr>
      </thead>
      <tbody>
      <ng-container *ngFor="let techniqueObject of basicTable.data">
        <tr *ngFor="let tacticObject of techniqueObject.tactics">
          <td>{{tacticObject.tactic}}: {{tacticObject.total_tickets}}</td>
        </tr>
      </ng-container>
      </tbody>
    </nz-table>
  </div>
</div>

CodePudding user response:

Here's a quick StackBlitz example I did to try to achieve what I think you wanted to achieve.

Basically, the strategy is as follows:

// ngOnInit:
// determine how many tactics have each technique:
const tacticsCountPerTechnique = this.data.map(
  (technique) => technique.tactics.length
);

// determine what's the max count of tactics in order to know how many rows to display:
const maxTacticsCount = Math.max.apply(null, tacticsCountPerTechnique);

// define a rowIndices array to conviniently render rows and tactics:
this.rowIndices = new Array(maxTacticsCount).fill(null).map((_, i) => i);

Following this approach your HTML would look like this:

  <tbody>
    <!-- display rows based on max number of tactics -->
    <tr *ngFor="let index of rowIndices">
      <!-- display columns based on techniques to match headers -->
      <td *ngFor="let technique of basicTable.data">
        <!-- display tactic info using row index as reference -->
        <!-- some techniques may have more tactics than others so we display info only when there's a tactic for that index with ngIf -->
        <ng-container *ngIf="technique.tactics[index] as tactic">
          {{ tactic.tactic }}:
          {{ tactic.total_tickets }}
        </ng-container>
      </td>
    </tr>
  </tbody>

There might be a better approach but I hope you get the idea.

  • Related