Home > Software engineering >  Angular Mat-Table with Dynamic Columns generate and Data should be populated in horizontal way
Angular Mat-Table with Dynamic Columns generate and Data should be populated in horizontal way

Time:12-05

I have a requirement where I need to populate the mat-table with the below mentioned Array of JSON object in horizontal format.

Please find the input array :-

[{
        "SAMPLERULEID": 69,
        "SAMPLERULENAME": "Sample1",
        "SAMPLERULECONDITIONS": [{
                "SAMPLERULECONDITIONID": 148,
                "SAMPLERULEID": 69,
                "SAMPLERULENAME": "Sample1",
                "CONDITIONFIELDID": 1,
                "DISPLAYNAME": "Country",
                "OPERATOR": "=",
                "COUNT": 10
            },
            {
                "SAMPLERULECONDITIONID": 149,
                "SAMPLERULEID": 69,
                "SAMPLERULENAME": "Sample1",
                "CONDITIONFIELDID": 2,
                "DISPLAYNAME": "State",
                "OPERATOR": "=",
                "COUNT": 11
            },
            {
                "SAMPLERULECONDITIONID": 150,
                "SAMPLERULEID": 69,
                "SAMPLERULENAME": "Sample1",
                "CONDITIONFIELDID": 3,
                "DISPLAYNAME": "City",
                "OPERATOR": "=",
            },
            {
                "SAMPLERULECONDITIONID": 151,
                "SAMPLERULEID": 69,
                "SAMPLERULENAME": "Sample1",
                "CONDITIONFIELDID": 4,
                "DISPLAYNAME": "Town",
                "OPERATOR": "IS NULL"
            }
        ],
    },
    {
        "SAMPLERULEID": 80,
        "SAMPLERULENAME": "Sample123",
        "SAMPLERULECONDITIONS": [{
            "SAMPLERULECONDITIONID": 208,
            "SAMPLERULEID": 80,
            "SAMPLERULENAME": "Sample123",
            "CONDITIONFIELDID": 92,
            "DISPLAYNAME": "Date",
            "OPERATOR": "IS NOT NULL",
            "COUNT": 12
        }],
    },
    {
        "SAMPLERULEID": 74,
        "SAMPLERULENAME": "Sample2",
        "SAMPLERULECONDITIONS": [{
                "SAMPLERULECONDITIONID": 153,
                "SAMPLERULEID": 74,
                "SAMPLERULENAME": "Sample2",
                "CONDITIONFIELDID": 89,
                "DISPLAYNAME": "Primary",
                "OPERATOR": "IS NOT NULL",
                "COUNT": 5
            },
            {
                "SAMPLERULECONDITIONID": 156,
                "SAMPLERULEID": 74,
                "SAMPLERULENAME": "Sample2",
                "CONDITIONFIELDID": 90,
                "DISPLAYNAME": "Secondary",
                "OPERATOR": ">",
                "COUNT": 9
            },
            {
                "SAMPLERULECONDITIONID": 157,
                "SAMPLERULEID": 74,
                "SAMPLERULENAME": "Sample2",
                "CONDITIONFIELDID": 89,
                "DISPLAYNAME": "Third",
                "OPERATOR": "IS NULL",
                "COUNT": 99
            }
        ],
    }
]

and Needed the Mat-table output in the below format..

enter image description here

here the column names are generated dynamically depending upon the array by incrementing count by 1 for condition string.

Please find the .ts file...

  export class SamplePocComponent implements OnInit {
    
      lstRulesCheck: MatTableDataSource<any>;
    
  displayedColumns3: string[] = [
    'SAMPLERULENAME','DISPLAYNAME',
  ];
    
      displayedColumns4: any[] = ['SAMPLERULENAME'];
    
      payload: any[] = []; // This is the input XML which is posted in top of the discussion
    
      count: number;
    
      constructor() {}
    
      ngOnInit() {
        this.getSampleRules();
      }
    
      getSampleRules() {
    
        this.lstRulesCheck = new MatTableDataSource(this.payload);
    
        this.payload.forEach((element) => {
          if(element.SAMPLERULECONDITIONS[0] !== undefined) {
            if(element.SAMPLERULECONDITIONS.length > 0) {
              if(this.count > element.SAMPLERULECONDITIONS.length){
              } else {
                this.count = element.SAMPLERULECONDITIONS.length;
              }
            }
          }
        })
    
        for (let i = 1; i <= this.count; i  ) {
          this.displayedColumns4.push('condition'  i);
        }
      }
     getVal(col, payload) {

if (payload.SAMPLERULECONDITIONS[0] !== undefined) {
  this.value = col.substring(9) - 1;

  this.one = "";
  this.two = "";
  this.three = "";

  if (payload.SAMPLERULECONDITIONS && payload.SAMPLERULECONDITIONS[this.value] && payload.SAMPLERULECONDITIONS[this.value].DISPLAYNAME) {
    this.one = payload.SAMPLERULECONDITIONS[this.value].DISPLAYNAME;
  }
  if (payload.SAMPLERULECONDITIONS && payload.SAMPLERULECONDITIONS[this.value] && payload.SAMPLERULECONDITIONS[this.value].OPERATOR) {
    this.two = payload.SAMPLERULECONDITIONS[this.value].OPERATOR;
  }
  if (payload.SAMPLERULECONDITIONS && payload.SAMPLERULECONDITIONS[this.value] && payload.SAMPLERULECONDITIONS[this.value].COUNT) {
    this.three = payload.SAMPLERULECONDITIONS[this.value].COUNT;
  }


  //return this.one   this.two   this.three;

  if(this.one !== "" || this.two !== "" || this.three !== ""){
    return `<td mat-cell> ${this.one}</td>
    <td mat-cell> ${this.two}</td>
    <td mat-cell> ${this.three} </td>`
  } else {
    return "";
  }  
}

}

    }

Please find the Mat-table code.. As of now I am able to print only Sample Name..

<table mat-table [dataSource]="lstRulesCheck" class="mat-elevation-z8">
                <ng-container *ngFor="let col of displayedColumns4" [matColumnDef]="col">
        <th mat-header-cell *matHeaderCellDef> {{col}} </th>
        <ng-container *ngIf="col === 'SAMPLERULENAME'">
            <td mat-cell *matCellDef="let element1"> {{element1.SAMPLERULENAME}} </td>
        </ng-container>
        <ng-container *ngIf="col !== 'SAMPLERULENAME'">
            <td mat-cell style="word-break: break-all; max-width: 30px;padding-left: 5px;" *matCellDef="let element" [innerHTML]="getVal(col,element)"></td>
        </ng-container>
    </ng-container>

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

    </table>

I am facing issue while adding the dynamic column names and data needs to be divided depending upon columns.

Could you please help me to achieve the above requirement (screenshot).

CodePudding user response:

displayedColumns: string[] = ['SAMPLERULENAME','DISPLAYNAME1','OPERATOR1','COUNT1','DISPLAYNAME2','OPERATOR2','COUNT2','DISPLAYNAME3','OPERATOR3','COUNT3','DISPLAYNAME4','OPERATOR4','COUNT4'];
  dataSource = ELEMENT_DATA;

  getValue(element, colname){
   console.log(element);
   var lastChar = colname.substr(colname.length - 1);
   console.log(lastChar);
   colname = colname.slice(0, -1); 
   console.log(colname);
   
   if(element["SAMPLERULECONDITIONS"   lastChar]){
    return (element["SAMPLERULECONDITIONS"   lastChar][colname]);
   }
  }

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">

<!-- Position Column -->

<ng-container *ngFor="let col of displayedColumns; let i = index" [matColumnDef]="col">

<ng-container  *ngIf="col === 'SAMPLERULENAME'" matColumnDef="SAMPLERULENAME">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell *matCellDef="let element"> {{element.SAMPLERULENAME}} </td>
</ng-container>

<ng-container *ngIf="col !== 'SAMPLERULENAME'">
    <th mat-header-cell *matHeaderCellDef>  </th>
    <td mat-cell *matCellDef="let element">
    {{getValue(element, col)}}
    </td>      
  </ng-container>  
  
</ng-container>

<!-- Header row first group -->
<ng-container matColumnDef="header-row-first-group">
<th mat-header-cell *matHeaderCellDef 
    [style.text-align]="center"
    [attr.colspan]="1"> 
  Name
</th>
</ng-container>

<!-- Header row second group -->
<ng-container matColumnDef="header-row-second-group">
<th mat-header-cell *matHeaderCellDef [attr.colspan]="3"> Second group </th>
</ng-container>

<!-- Header row 3 group -->
<ng-container matColumnDef="header-row-3-group">
<th mat-header-cell *matHeaderCellDef [attr.colspan]="3"> Condition1 </th>
</ng-container>

<!-- Header row 4 group -->
<ng-container matColumnDef="header-row-4-group">
<th mat-header-cell *matHeaderCellDef [attr.colspan]="3">Condition2 </th>
</ng-container>

<!-- Header row 4 group -->
<ng-container matColumnDef="header-row-5-group">
<th mat-header-cell *matHeaderCellDef [attr.colspan]="3"> Condition3 </th>
</ng-container>



<tr mat-header-row *matHeaderRowDef="['header-row-first-group', 'header-row-second-group','header-row-3-group','header-row-4-group','header-row-5-group']"></tr>


<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

<!-- Copyright 2018 Google Inc. All Rights Reserved.
  Use of this source code is governed by an MIT-style license that
  can be found in the LICENSE file at http://angular.io/license -->

enter image description here

CodePudding user response:

Implemented the below HTML file to have the columns generate dynamically and modified the ts file to get the corresponding data.

  getValue(element, colname){

    // if (element && element.SAMPLERULECONDITIONS[0] !== undefined) {
      var lastChar = colname.substr(colname.length - 1) - 1;      
      colname = colname.slice(0, -1); 

      if (element.SAMPLERULECONDITIONS && element.SAMPLERULECONDITIONS[lastChar]) {
        return (element["SAMPLERULECONDITIONS"][lastChar][colname]);
      }
   }

Corresponding HTML File :- Still I need to add Action tag at the end with EDIT and Delete row

<div class="data" #TABLE>
    <table mat-table [dataSource]="lstRulesCheck" class="mat-elevation-z8">
        <ng-container *ngFor="let col of displayedColumns1; let i = index" [matColumnDef]="col">
            <ng-container *ngIf="col === 'SAMPLERULENAME'">
                <th mat-header-cell *matHeaderCellDef> </th>
                <td mat-cell *matCellDef="let element"> {{element.SAMPLERULENAME}} </td>
            </ng-container>

            <ng-container *ngIf="col !== 'SAMPLERULENAME'">
                <th mat-header-cell *matHeaderCellDef> </th>
                <td mat-cell *matCellDef="let element">
                    {{getValue(element, col)}}
                </td>
            </ng-container>

        </ng-container>

        <ng-container *ngFor="let groupName of displayedGroupColumns; let i = index; let f=first"
            [matColumnDef]="groupName">

            <ng-container *ngIf="f; else colSpan">
                <th mat-header-cell *matHeaderCellDef [attr.colspan]="1">
                    Name
                </th>
            </ng-container>
            
            <ng-template #colSpan>
                <th mat-header-cell *matHeaderCellDef style="text-align: center;" [attr.colspan]="3">
                    {{groupName}}
                </th>
            </ng-template>
        </ng-container>

        <tr mat-header-row *matHeaderRowDef="displayedGroupColumns"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns1;"></tr>
    </table>
</div>
  • Related