问题
I have a dynamic CDK Angular Material mat-table that I have fixed a mat-checkbox to. It is populating data, but it is not allowing me to set the correct column headers. Everything that gets displayed is from the key:value pairs from the UserInformation array. However, I need to set a second array to display the correct header names as I will not have control of the key names coming from the API and will need to set them in the TypeScript. Not all information coming from the API will be displayed in the table. I will have multiple tables as well and need to make this completely reusable to where on the content being displayed will change in the TypeScript, everything else will be injected.
Right now I'm down to just getting the displayedColumn names to appear correctly in the table.
//Dummy Data
const UserInformation: any[] = [
{
'firstName': 'Jane',
'lastName': 'Doe',
'jobRole': 'My Job',
'company': 'Work',
'status': true,
'employeeID': '23456',
'phone': '(253)227-2567',
'email': 'myemail@myemail.com'
},
{
'firstName': 'John',
'lastName': 'Smith',
'jobRole': 'My Job',
'company': 'Work',
'status': true,
'employeeID': '23456',
'phone': '(253)227-2567',
'email': 'myemail@myemail.com'
}
];
columns: any;
// Material Table Columns
@Input() public content: any;
public rows = new MatTableDataSource<any>();
headers = [
{ filed: '',
},
{ field: 'firstName',
title: 'First Name',
cell: (element: any) => `${element.firstName}`,
},
{ field: 'lastName',
title: 'Last Name',
cell: (element: any) => `${element.lastName}`,
},
{ field: 'employeeID',
title: 'Employee ID',
cell: (element: any) => `${element.employeeID}`,
},
{ field: 'jobRole',
title: 'Job Role',
cell: (element: any) => `${element.jobRole}`,
},
{ field: 'email',
title: 'Email',
cell: (element: any) => `${element.email}`,
}
];
displayedColumns = this.headers.map(c => c.field);
public selection = new SelectionModel<any>(true, []);
// Material Table Functionality
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
@ViewChild('tableResults') tableResults;
this.showUsers();
// Material Table
public filterBy(event: any): void {
const filterBy: string = event.target.value;
this.rows.filter = filterBy;
}
public isAllSelected() {
const numSelected = this.selection.selected.length;
const numRows = this.rows.data.length;
return numSelected === numRows;
}
public masterToggle() {
this.isAllSelected() ?
this.selection.clear() :
this.rows.data.forEach(row => this.selection.select(row));
}
public checkboxLabel(row?: any): string {
return (!row)
? `${this.isAllSelected() ? 'select' : 'deselect'} all`
: `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.position + 1}`;
}
private updateRows(): void {
this.rows = new MatTableDataSource<any>(this.displayedColumns);
this.rows.sort = this.sort;
this.rows.paginator = this.paginator;
}
private updateColumns(): void {
this.columns = ['select'];
for (const column of Object.keys(this.displayedColumns[0])) {
this.columns.push(column);
}
}
private updateTable(): void {
if (this.displayedColumns) {
this.updateRows();
this.updateColumns();
}
}
public showUsers(): void {
this.displayedColumns = UserInformation;
this.updateTable();
this.selection.clear();
}
item1() {
alert('solved!!');
// this.target.classList.add('class3');
}
dragStarted(event: CdkDragStart<string[]>, index: number ) {
if (event) {
this.previousIndex = index;
}
}
dropListDropped(event: CdkDropList<string[]>, index: number) {
if (event) {
moveItemInArray(this.columns, this.previousIndex, index);
}
}
//HTML TABLE
<mat-table [dataSource]="rows" class="mat-elevation-z8" cdkDropListGroup matSort matSortActive="symbol" matSortDirection="asc">
<ng-container *ngFor="let column of columns; let i = index" matColumnDef="{{column}}">
<span *ngIf="i === 0">
<mat-header-cell *matHeaderCellDef>
<mat-checkbox (change)="$event ? masterToggle() : null"
[checked]="selection.hasValue() && isAllSelected()"
[indeterminate]="selection.hasValue() && !isAllSelected()"
[aria-label]="checkboxLabel()">
</mat-checkbox>
</mat-header-cell>
<mat-cell *matCellDef="let row">
<mat-checkbox (click)="$event.stopPropagation()"
(change)="$event ? selection.toggle(row) : null"
[checked]="selection.isSelected(row)"
[aria-label]="checkboxLabel(row)">
</mat-checkbox>
</mat-cell>
</span>
<span *ngIf="i !== 0">
<mat-header-cell *matHeaderCellDef
cdkDropList
cdkDropListLockAxis="x"
cdkDropListOrientation="horizontal"
(cdkDropListDropped)="dropListDropped($event, i)"
cdkDrag
(cdkDragStarted)="dragStarted($event, i)"
[cdkDragData]="{name: column, columIndex: i}"
mat-sort-header>
{{ column }}
</mat-header-cell>
<mat-cell *matCellDef="let row" > {{ row[column] }} </mat-cell>
</span>
</ng-container>
<mat-header-row *matHeaderRowDef="columns; sticky: true;"></mat-header-row>
<mat-row *matRowDef="let row; columns: columns;" (click)="selection.toggle(row)" [routerLink]="['']"></mat-row>
</mat-table>
<mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
Sorry this is a lot of code, but there is a lot happening in this table. I'm really just hoping to get pointed in the right direction to get the table headers listed from "header" that is connected to displayedColumns to display in the table header instead of the value from the UserInformation array. Any help is greatly appreciated.
回答1:
Instead of using an additional array for headers, simply add a pipe in mat-header-cell
that transforms the key to a displayed value.
See this Stackblitz for example.
来源:https://stackoverflow.com/questions/57812228/cdk-angular-table-with-dynamic-checkboxes-not-finding-correct-column-names