在 mat-table 中正确显示按动态列分组的数据列表
Correctly display in a mat-table a data list grouped with dynamic columns
我有一个问题,很遗憾我无法解决。
我的APIreturns我的数据列表是这样的:
[
{grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1"},
{grade: "Grade B", id: 2, ifsGrade: "B1XX", ifsType: "02XX", points: 15, type: "Type_1"},
{grade: "Grade C", id: 3, ifsGrade: "C1XX", ifsType: "03XX", points: 1, type: "Type_1"},
{grade: "Grade A", id: 4, ifsGrade: "A2XX", ifsType: "04XX", points: 23, type: "Type_2"},
{grade: "Grade B", id: 5, ifsGrade: "B2XX", ifsType: "05XX", points: 26, type: "Type_2"}
]
我按如下类型对数据进行分组:
Array.prototype.groupBy = function(k) {
return this.reduce((acc, item) => (acc[item[k]] = [...(acc[item[k]] || []), item], acc), {});
};
var TABLE_DATA = Object.values(API_DATA.groupBy("type"));
[
[
{grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1"},
{grade: "Grade B", id: 2, ifsGrade: "B1XX", ifsType: "02XX", points: 15, type: "Type_1"},
{grade: "Grade C", id: 3, ifsGrade: "C1XX", ifsType: "03XX", points: 1, type: "Type_1"}
],
[
{grade: "Grade A", id: 4, ifsGrade: "A2XX", ifsType: "04XX", points: 23, type: "Type_2"},
{grade: "Grade B", id: 5, ifsGrade: "B2XX", ifsType: "05XX", points: 26, type: "Type_2"}
]
]
我希望能够像这样在 Angular Material mat-table 中显示数据:
所以我确实有一个数据源列表,但该列表的元素也是列表。所以我不知道如何正确显示项目。
因此,对于 table 列,您需要这样的动态内容,但我不知道如何:
<ng-container matColumnDef="{{column}}" *ngFor="let column of definedColumns">
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let element"> {{element[column]}} </td>
</ng-container>
Stackblitz link here
感谢您的帮助
您需要遍历数据并将不同的值映射到新对象。
这是一个工作堆栈示例
https://stackblitz.com/edit/datasource-mat-table-with-group-by-ay2rbh
以及来自 stackblitz 的相关函数
convertedData: ElementType[];
// creates "gradeX" from "Grade X"
convertGradeToGradeKey(grade: string): string{
return `grade${grade.split(" ")[1]}`;
}
// probably worth typing this "data" properly as well...
mapDataFromApi(data: any[]): void {
// using a map so we don't have to iterate the whole list to find type === "someType" every time
let mappedData = new Map<string, ElementType>();
data.forEach(val => {
// get the existing value from the map, or ceate a "new" one if its not there
let currentVal = mappedData.get(val.type) || {type: val.type, gradeA: undefined, gradeB: undefined, gradeC: undefined};
// get the "grade key" from the string value
const gradeKey = this.convertGradeToGradeKey(val.grade);
// get the new value, which will be the curent value + this row's "poiints"
const newGradeValue: number = (currentVal[gradeKey] || 0) + val.points;
// merge the current value object with the new property
currentVal = {...currentVal, [gradeKey]: newGradeValue };
// add upate the value in the set
mappedData.set(val.type, currentVal);
})
// create a normal array from that mapped data
this.convertedData = [...mappedData].map(([key, val]) => val);
}
按 type
分组的数据初始化:
ngOnInit() {
this.API_DATA = [
{grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1"},
{grade: "Grade B", id: 2, ifsGrade: "B1XX", ifsType: "02XX", points: 15, type: "Type_1"},
{grade: "Grade C", id: 3, ifsGrade: "C1XX", ifsType: "03XX", points: 1, type: "Type_1"},
{grade: "Grade A", id: 4, ifsGrade: "A2XX", ifsType: "04XX", points: 23, type: "Type_2"},
{grade: "Grade B", id: 5, ifsGrade: "B2XX", ifsType: "05XX", points: 16, type: "Type_2"}
];
const key = 'type'
const dataTable = Object.values(this.API_DATA.reduce((acc, item) => (acc[item[key]] = [...(acc[item[key]] || []), item], acc), {}));
this.dataSource = dataTable;
}
mat-table
Angular material 具有动态列:
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container matColumnDef="{{column}}" *ngFor="let column of definedColumns; let index = index;">
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let elements">
<span *ngFor="let element of elements; let first = first;">
<span *ngIf="index == 0 && first">{{element.type}}</span>
<span *ngIf="element.grade == column">{{element.points}}</span>
</span>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef class="text-right">
<button mat-icon-button (click)="log('add')">
<mat-icon color="accent">add_circle_outline</mat-icon>
</button>
</th>
<td mat-cell *matCellDef="let gradingIndex" class="text-right">
<button mat-icon-button>
<mat-icon color="primary" (click)="log(gradingIndex)">edit</mat-icon>
</button>
<button mat-icon-button (click)="log(gradingIndex)">
<mat-icon color="warn">delete</mat-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
结果:
堆栈闪电战: here
我有一个问题,很遗憾我无法解决。
我的APIreturns我的数据列表是这样的:
[
{grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1"},
{grade: "Grade B", id: 2, ifsGrade: "B1XX", ifsType: "02XX", points: 15, type: "Type_1"},
{grade: "Grade C", id: 3, ifsGrade: "C1XX", ifsType: "03XX", points: 1, type: "Type_1"},
{grade: "Grade A", id: 4, ifsGrade: "A2XX", ifsType: "04XX", points: 23, type: "Type_2"},
{grade: "Grade B", id: 5, ifsGrade: "B2XX", ifsType: "05XX", points: 26, type: "Type_2"}
]
我按如下类型对数据进行分组:
Array.prototype.groupBy = function(k) {
return this.reduce((acc, item) => (acc[item[k]] = [...(acc[item[k]] || []), item], acc), {});
};
var TABLE_DATA = Object.values(API_DATA.groupBy("type"));
[
[
{grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1"},
{grade: "Grade B", id: 2, ifsGrade: "B1XX", ifsType: "02XX", points: 15, type: "Type_1"},
{grade: "Grade C", id: 3, ifsGrade: "C1XX", ifsType: "03XX", points: 1, type: "Type_1"}
],
[
{grade: "Grade A", id: 4, ifsGrade: "A2XX", ifsType: "04XX", points: 23, type: "Type_2"},
{grade: "Grade B", id: 5, ifsGrade: "B2XX", ifsType: "05XX", points: 26, type: "Type_2"}
]
]
我希望能够像这样在 Angular Material mat-table 中显示数据:
所以我确实有一个数据源列表,但该列表的元素也是列表。所以我不知道如何正确显示项目。
因此,对于 table 列,您需要这样的动态内容,但我不知道如何:
<ng-container matColumnDef="{{column}}" *ngFor="let column of definedColumns">
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let element"> {{element[column]}} </td>
</ng-container>
Stackblitz link here
感谢您的帮助
您需要遍历数据并将不同的值映射到新对象。
这是一个工作堆栈示例 https://stackblitz.com/edit/datasource-mat-table-with-group-by-ay2rbh
以及来自 stackblitz 的相关函数
convertedData: ElementType[];
// creates "gradeX" from "Grade X"
convertGradeToGradeKey(grade: string): string{
return `grade${grade.split(" ")[1]}`;
}
// probably worth typing this "data" properly as well...
mapDataFromApi(data: any[]): void {
// using a map so we don't have to iterate the whole list to find type === "someType" every time
let mappedData = new Map<string, ElementType>();
data.forEach(val => {
// get the existing value from the map, or ceate a "new" one if its not there
let currentVal = mappedData.get(val.type) || {type: val.type, gradeA: undefined, gradeB: undefined, gradeC: undefined};
// get the "grade key" from the string value
const gradeKey = this.convertGradeToGradeKey(val.grade);
// get the new value, which will be the curent value + this row's "poiints"
const newGradeValue: number = (currentVal[gradeKey] || 0) + val.points;
// merge the current value object with the new property
currentVal = {...currentVal, [gradeKey]: newGradeValue };
// add upate the value in the set
mappedData.set(val.type, currentVal);
})
// create a normal array from that mapped data
this.convertedData = [...mappedData].map(([key, val]) => val);
}
按 type
分组的数据初始化:
ngOnInit() {
this.API_DATA = [
{grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1"},
{grade: "Grade B", id: 2, ifsGrade: "B1XX", ifsType: "02XX", points: 15, type: "Type_1"},
{grade: "Grade C", id: 3, ifsGrade: "C1XX", ifsType: "03XX", points: 1, type: "Type_1"},
{grade: "Grade A", id: 4, ifsGrade: "A2XX", ifsType: "04XX", points: 23, type: "Type_2"},
{grade: "Grade B", id: 5, ifsGrade: "B2XX", ifsType: "05XX", points: 16, type: "Type_2"}
];
const key = 'type'
const dataTable = Object.values(this.API_DATA.reduce((acc, item) => (acc[item[key]] = [...(acc[item[key]] || []), item], acc), {}));
this.dataSource = dataTable;
}
mat-table
Angular material 具有动态列:
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container matColumnDef="{{column}}" *ngFor="let column of definedColumns; let index = index;">
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let elements">
<span *ngFor="let element of elements; let first = first;">
<span *ngIf="index == 0 && first">{{element.type}}</span>
<span *ngIf="element.grade == column">{{element.points}}</span>
</span>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef class="text-right">
<button mat-icon-button (click)="log('add')">
<mat-icon color="accent">add_circle_outline</mat-icon>
</button>
</th>
<td mat-cell *matCellDef="let gradingIndex" class="text-right">
<button mat-icon-button>
<mat-icon color="primary" (click)="log(gradingIndex)">edit</mat-icon>
</button>
<button mat-icon-button (click)="log(gradingIndex)">
<mat-icon color="warn">delete</mat-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
结果:
堆栈闪电战: here