我正在开发一个 Angular 项目,在该项目中我使用 Angular Material 的 mat-table 并启用了排序。排序功能有效,但当我使用 ts 代码更改排序时,列标题中的箭头无法正确显示。
HTML:
<div class="cpage">
<div class="left-margin"></div>
<div class="left">
<form-card header="Left" [enableBottomPadding]="true">
<button mat-raised-button (click)="actionB1()">B1</button>
</form-card>
</div>
<div class="gap-between"></div>
<div class="right">
<form-card header="DataTable" [enableBottomPadding]="true">
<div style="width: 100%; max-height:90vh; overflow-x:auto">
<mat-table [dataSource]="dataSource" matSort #sort1="matSort">
<ng-container matColumnDef="position">
<mat-header-cell mat-sort-header *matHeaderCellDef> No.</mat-header-cell>
<mat-cell *matCellDef="let element"> {{ element.position }}</mat-cell>
</ng-container>
<ng-container matColumnDef="name">
<mat-header-cell mat-sort-header *matHeaderCellDef> Name</mat-header-cell>
<mat-cell *matCellDef="let element"> {{ element.name }}</mat-cell>
</ng-container>
<ng-container matColumnDef="weight">
<mat-header-cell mat-sort-header *matHeaderCellDef> Weight</mat-header-cell>
<mat-cell *matCellDef="let element"> {{ element.weight }}</mat-cell>
</ng-container>
<!-- additional weight columns -->
<ng-container matColumnDef="weight1">
<mat-header-cell *matHeaderCellDef> Weight</mat-header-cell>
<mat-cell *matCellDef="let element"> {{ element.weight }}</mat-cell>
</ng-container>
<ng-container matColumnDef="symbol">
<mat-header-cell *matHeaderCellDef> Symbol</mat-header-cell>
<mat-cell *matCellDef="let element"> {{ element.symbol }}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</div>
</form-card>
</div>
<div class="right-margin"></div>
</div>
TS:
import { AfterViewInit, ChangeDetectorRef, Component, ViewChild } from '@angular/core';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from "@angular/material/table";
export interface PeriodicElement {
name: string;
position: number;
weight: number;
symbol: string;
}
const ELEMENT_DATA: PeriodicElement[] = [
{ position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
{ position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
{ position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
{ position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' },
{ position: 5, name: 'Boron', weight: 10.811, symbol: 'B' },
{ position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C' },
{ position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N' },
{ position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O' },
{ position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F' },
{ position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' },
];
@Component({
selector: 'app-debug-table',
templateUrl: './debug-table.component.html',
styleUrls: ['./debug-table.component.scss']
})
export class DebugTableComponent implements AfterViewInit {
displayedColumns: string[] = ['position', 'name', 'weight', 'weight1', 'symbol'];
dataSource = new MatTableDataSource(ELEMENT_DATA);
@ViewChild('sort1', { static: false }) sort1: MatSort;
constructor(private cdr: ChangeDetectorRef) {}
ngAfterViewInit() {
this.dataSource.sort = this.sort1;
}
actionB1() {
if (this.sort1.active == 'name') {
this.sort1.active = 'weight';
} else {
this.sort1.active = 'name';
}
this.dataSource.sort = this.sort1;
this.cdr.detectChanges();
}
}
问题:排序有效,但列标题旁边的排序箭头无法正确更新。单击“B1”按钮可在“名称”和“重量”之间切换排序,但 mat-sort-header 标题上的箭头似乎不遵循此切换。
我尝试过的:
已验证我已导入 Angular Material 排序模块。 检查 matSort 和 mat-sort-header 是否正确添加到 mat-table 和标题单元格中。 更新排序后调用 detectorChanges 来尝试刷新视图。 以前有人遇到过这个问题吗?关于如何让箭头正确显示有什么想法吗?
角度:16 角度材质:16
您可以使用
sort
的dataSource.sort
方法,它接受MatSortable
的接口输入。
export declare interface MatSortable {
/** The id of the column being sorted. */
id: string;
/** Starting sort direction. */
start: SortDirection;
/** Whether to disable clearing the sorting state. */
disableClear: boolean;
}
export declare type SortDirection = 'asc' | 'desc' | '';
然后我们就可以使用下面的方法了。
actionB1() {
let active = null;
if (this.sort1.active == 'name') {
active = 'weight';
} else {
active = 'name';
}
this.dataSource.sort!.sort({
id: active,
start: 'asc',
disableClear: true,
});
// this.cdr.detectChanges();
}
<button mat-raised-button (click)="actionB1()">B1</button>
<table
mat-table
matSort
[dataSource]="dataSource"
class="mat-elevation-z8"
(matSortChange)="sortData($event)"
>
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- Position Column -->
<ng-container matColumnDef="position">
<th mat-header-cell *matHeaderCellDef mat-sort-header="position">No.</th>
<td mat-cell *matCellDef="let element">{{element.position}}</td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header="name">Name</th>
<td mat-cell *matCellDef="let element">{{element.name}}</td>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef mat-sort-header="weight">Weight</th>
<td mat-cell *matCellDef="let element">{{element.weight}}</td>
</ng-container>
<!-- Symbol Column -->
<ng-container matColumnDef="symbol">
<th mat-header-cell *matHeaderCellDef mat-sort-header="symbol">Symbol</th>
<td mat-cell *matCellDef="let element">{{element.symbol}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
import { Component, ViewChild, ChangeDetectorRef, inject } from '@angular/core';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { MatSort } from '@angular/material/sort';
import { MatSortModule, Sort } from '@angular/material/sort';
export interface PeriodicElement {
name: string;
position: number;
weight: number;
symbol: string;
}
const ELEMENT_DATA: PeriodicElement[] = [
{ position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
{ position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
{ position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
{ position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' },
{ position: 5, name: 'Boron', weight: 10.811, symbol: 'B' },
{ position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C' },
{ position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N' },
{ position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O' },
{ position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F' },
{ position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' },
];
function compare(a: number | string, b: number | string, isAsc: boolean) {
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}
/**
* @title Basic use of `<table mat-table>`
*/
@Component({
selector: 'table-basic-example',
styleUrl: 'table-basic-example.css',
templateUrl: 'table-basic-example.html',
standalone: true,
imports: [MatTableModule, MatSortModule],
})
export class TableBasicExample {
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
dataSource = new MatTableDataSource(ELEMENT_DATA);
cdr = inject(ChangeDetectorRef);
@ViewChild(MatSort, { static: false }) sort1: MatSort;
ngAfterViewInit() {
this.dataSource.sort = this.sort1;
}
actionB1() {
let active = null;
if (this.sort1.active == 'name') {
active = 'weight';
} else {
active = 'name';
}
this.dataSource.sort!.sort({
id: active,
start: 'asc',
disableClear: true,
});
// this.cdr.detectChanges();
}
sortData(sort: Sort) {
const data = this.dataSource.data.slice();
if (!sort.active || sort.direction === '') {
this.dataSource.data = data;
return;
}
this.dataSource.data = data.sort((a, b) => {
const isAsc = sort.direction === 'asc';
switch (sort.active) {
case 'name':
return compare(a.name, b.name, isAsc);
case 'weight':
return compare(a.weight, b.weight, isAsc);
case 'symbol':
return compare(a.symbol, b.symbol, isAsc);
default:
return 0;
}
});
}
}