locked
Angular Material grid looping thru collection array error RRS feed

  • Question

  • User956626884 posted

    Hi,

    I am having some issue with my Angular Material UI grid where I am looping thru collection of Array

    Here is typescript collection

    const DATA: nyData[] = [
      { weekEnd: '2/3/2019', 
        date: ['1/28/2019','1/29/2019', '1/30/2019','1/31/2019','2/01/2019','2/02/2019','2/03/2019'], 
        priorYear:[3198.63, 3041.31, 3701.69, 3932.57, 5081.96, 7430.63, ,541.61],
        foreCastComp: ['20.62%','32.38%','-11.91%','-7.38%','-8.36%',	'-18.44%','-19.19%'],
        actDailyComp: ['N/A','N/A','N/A','N/A','N/A','N/A','N/A'],
        foreCast: [3858.31,	4026.14,	3260.82,	3642.32,	4657.33,	6060.73,	6094.70],
        actual: [0.00,	0.00,	0.00,	0.00,	0.00,	0.00,	0.00],
        foreCastVariant: [ -3858.31,	-4026.14,	-3260.82, 	-3642.32,	-4657.33,	-6060.73, 	-6094.70]
      }
    ]
    
    

    The error is the my Material Angular GRID looks like the following

    Date                                       Prior Year                        Forecast Comp                                    Daily Comp                         ForeCase                          Actual                       Variant
    
    1/28/2019,1/29/2019,1/30/2019,1/31/2019,2/01/2019,2/02/2019,2/03/2019            3198.63,3041.31,3701.69,3932.57,5081.96,7430.63,,541.61           20.62%,32.38%,-11.91%,-7.38%,-8.36%,-18.44%,-19.19%N/A,N/A,N/A,N/A,N/A,N/A,N/A3858.31,4026.14,3260.82,3642.32,4657.33,6060.73,6094.7
    0,0,0,0,0,0,0-3858.31,-4026.14,-3260.82,-3642.32,-4657.33,-6060.73,-6094.7

    All the array elements are displayed in 1 and the first row

    I am trying to use angular to loop thru the collection array to have the following GRID Look. 

    Thanks

     

    Date                           1/28/2019      1/29/2019      1/30/2019      1/31/2019      2/01/2019      2/02/2019      2/03/2019
    
    Prior Year                    3198.63          3041.31          3701.69          3932.57         5081.96          7430.63          541.61
    
    Forecast Comp                 20.62%           32.38%           -11.91%         -7.38%           -8.36%           -18.44%          -19.19%
    
    Daily Comp                    N/A                 N/A                N/A                N/A               N/A                 N/A                N/A'         
    
    ForeCase                     3858.31           4026.14           3260.82          3642.32        4657.33          6060.73            6094.70
    
    Actual                       0.00                  0.00                0.00                0.00               0.00               0.00                   0.00
    
    Variant                       -3858.31        -4026.14         -3260.82         -3642.32        4657.33          6060.73            6094.70

    Friday, February 8, 2019 7:28 PM

Answers

  • User1843160919 posted

    The trick is all about transforming the DATA  from "vertical" to "horizontal" and generate columns dynamically. 

    Here's a complete code of working example:

    1. Create a template as below :

    <div>
      <mat-table #table [dataSource]="dataSource">
    
        <ng-container *ngFor="let column of columns" [cdkColumnDef]="column.columnName">
          <mat-header-cell *cdkHeaderCellDef>{{ column.displayName}}</mat-header-cell>
          <mat-cell *cdkCellDef="let row">{{ column.cellFunc(row) }}</mat-cell>
        </ng-container>
        <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
        <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
      </mat-table>
    
    </div>

    2. and create a component  :

    @Component({
      selector: 'app-horizon-table',
      templateUrl: './horizon-table.component.html',
      styleUrls: ['horizon-table.component.css'],
    })
    export class HorizonTableComponent {
    
      public dataSource: TableModel;
      public displayedColumns: string[];
      public columns: Column[] ;
    
      constructor(@Inject('BASE_URL') baseUrl: string) {
        
        const DATA = [
          {
            weekEnd: '2/3/2019',
            date: ['1/28/2019', '1/29/2019', '1/30/2019', '1/31/2019', '2/01/2019', '2/02/2019', '2/03/2019'],
            priorYear: [3198.63, 3041.31, 3701.69, 3932.57, 5081.96, 7430.63, 541.61],
            foreCastComp: ['20.62%', '32.38%', '-11.91%', '-7.38%', '-8.36%', '-18.44%', '-19.19%'],
            actDailyComp: ['N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A'],
            foreCast: [3858.31, 4026.14, 3260.82, 3642.32, 4657.33, 6060.73, 6094.70],
            actual: [0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
            foreCastVariant: [-3858.31, -4026.14, -3260.82, -3642.32, -4657.33, -6060.73, -6094.70]
          }
        ]
        this.columns = [];
        this.getAllowedColumns(DATA).forEach(c =>{
          this.columns.push({columnName:c, displayName:c,cellFunc:r=> r[c] })
        });
        this.displayedColumns = this.columns.map(a => a.columnName);
        this.dataSource = this.convertDATAToDataSource(DATA);
        console.log(this.dataSource, this.displayedColumns);
      }
    
      private _fields = [
        {columnName:"priorYear",displayName:"Prior Year"}, 
        {columnName:"foreCastComp",displayName:"Forecast Comp"}, 
        {columnName:"actDailyComp",displayName:"Daily Comp"},
        {columnName:"foreCast",displayName:"ForeCase"},
        {columnName:"actual",displayName:"Actual"},
        {columnName:"foreCastVariant",displayName: "Variant"}
      ];
    
      private getAllowedColumns(DATA) {
        var first = DATA[0];
        return ["date"].concat(first.date);
      }
      
      private convertDATAToDataSource(DATA: any) {
        var first = DATA[0];
        var matrix = [];
        var dates: string[] = first.date;
        this._fields.forEach(f => {
          var obj = {};
          obj["date"] = f.displayName;
          dates.forEach((date, idx) => {
            obj[date] = first[f.columnName][idx];
          });
          matrix.push(obj);
        });
        return matrix;
      }
    
    }
    
    
    
    interface TableModel { }
    
    interface Column{
      columnName: string,
      displayName: string,
      cellFunc:  (row:any)=>string, 
    }

    A screenshot of demo :

    demo

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, February 11, 2019 10:34 AM

All replies

  • User1843160919 posted

    The trick is all about transforming the DATA  from "vertical" to "horizontal" and generate columns dynamically. 

    Here's a complete code of working example:

    1. Create a template as below :

    <div>
      <mat-table #table [dataSource]="dataSource">
    
        <ng-container *ngFor="let column of columns" [cdkColumnDef]="column.columnName">
          <mat-header-cell *cdkHeaderCellDef>{{ column.displayName}}</mat-header-cell>
          <mat-cell *cdkCellDef="let row">{{ column.cellFunc(row) }}</mat-cell>
        </ng-container>
        <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
        <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
      </mat-table>
    
    </div>

    2. and create a component  :

    @Component({
      selector: 'app-horizon-table',
      templateUrl: './horizon-table.component.html',
      styleUrls: ['horizon-table.component.css'],
    })
    export class HorizonTableComponent {
    
      public dataSource: TableModel;
      public displayedColumns: string[];
      public columns: Column[] ;
    
      constructor(@Inject('BASE_URL') baseUrl: string) {
        
        const DATA = [
          {
            weekEnd: '2/3/2019',
            date: ['1/28/2019', '1/29/2019', '1/30/2019', '1/31/2019', '2/01/2019', '2/02/2019', '2/03/2019'],
            priorYear: [3198.63, 3041.31, 3701.69, 3932.57, 5081.96, 7430.63, 541.61],
            foreCastComp: ['20.62%', '32.38%', '-11.91%', '-7.38%', '-8.36%', '-18.44%', '-19.19%'],
            actDailyComp: ['N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A', 'N/A'],
            foreCast: [3858.31, 4026.14, 3260.82, 3642.32, 4657.33, 6060.73, 6094.70],
            actual: [0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
            foreCastVariant: [-3858.31, -4026.14, -3260.82, -3642.32, -4657.33, -6060.73, -6094.70]
          }
        ]
        this.columns = [];
        this.getAllowedColumns(DATA).forEach(c =>{
          this.columns.push({columnName:c, displayName:c,cellFunc:r=> r[c] })
        });
        this.displayedColumns = this.columns.map(a => a.columnName);
        this.dataSource = this.convertDATAToDataSource(DATA);
        console.log(this.dataSource, this.displayedColumns);
      }
    
      private _fields = [
        {columnName:"priorYear",displayName:"Prior Year"}, 
        {columnName:"foreCastComp",displayName:"Forecast Comp"}, 
        {columnName:"actDailyComp",displayName:"Daily Comp"},
        {columnName:"foreCast",displayName:"ForeCase"},
        {columnName:"actual",displayName:"Actual"},
        {columnName:"foreCastVariant",displayName: "Variant"}
      ];
    
      private getAllowedColumns(DATA) {
        var first = DATA[0];
        return ["date"].concat(first.date);
      }
      
      private convertDATAToDataSource(DATA: any) {
        var first = DATA[0];
        var matrix = [];
        var dates: string[] = first.date;
        this._fields.forEach(f => {
          var obj = {};
          obj["date"] = f.displayName;
          dates.forEach((date, idx) => {
            obj[date] = first[f.columnName][idx];
          });
          matrix.push(obj);
        });
        return matrix;
      }
    
    }
    
    
    
    interface TableModel { }
    
    interface Column{
      columnName: string,
      displayName: string,
      cellFunc:  (row:any)=>string, 
    }

    A screenshot of demo :

    demo

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, February 11, 2019 10:34 AM
  • User956626884 posted

    Thanks itminus. It helps to get started.

    Monday, February 11, 2019 2:38 PM