Answered by:
Angular Material grid looping thru collection array error

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 :
- 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 :
- 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