如何用mat-sort实现表格中dd-MM-yyyy格式日期的正确排序?
Angular mat-sort 正确排序 dd-MM-yyyy 格式日期
问题根源在于直接对dd-MM-yyyy格式的字符串进行排序时,mat-sort会按字典序比较字符串,只优先匹配前两位的"日"部分,完全忽略月份和年份,导致排序结果不符合日期逻辑。要解决这个问题,核心是把日期字符串转换为可正确比较的Date对象(或对应的时间戳)后再执行排序。
实现步骤
1. 编写日期解析辅助函数
先实现一个工具函数,把dd-MM-yyyy格式的字符串转换成标准Date对象:
parseDDMMYYYY(dateStr: string): Date | null { const dateParts = dateStr.split('-'); // 注意:JavaScript的Date月份是0起始(0=1月,11=12月),所以要减1 if (dateParts.length === 3) { return new Date(+dateParts[2], +dateParts[1] - 1, +dateParts[0]); } // 格式错误时返回null return null; }
2. 配置mat-sort的排序逻辑
根据你使用的排序方式,选择以下两种方案之一:
方案一:通过sortingDataAccessor全局配置(推荐)
如果使用MatTableDataSource,可以直接配置sortingDataAccessor,让日期列自动按时间戳排序:
import { MatTableDataSource } from '@angular/material/table'; import { Sort, MatSort } from '@angular/material/sort'; import { ViewChild, AfterViewInit } from '@angular/core'; // 假设你的数据类型定义 interface YourDataType { id: number; date: string; // dd-MM-yyyy格式 // 其他字段... } export class YourComponent implements AfterViewInit { dataSource = new MatTableDataSource<YourDataType>([]); displayedColumns = ['id', 'date']; // 替换成你的列名 @ViewChild(MatSort) sort!: MatSort; ngAfterViewInit() { this.dataSource.sort = this.sort; // 配置排序访问器 this.dataSource.sortingDataAccessor = (item, property) => { if (property === 'date') { // 替换成你的日期列字段名 const date = this.parseDDMMYYYY(item.date); // 转成时间戳(数字类型),确保排序逻辑正确 return date ? date.getTime() : ''; } // 其他字段按默认逻辑处理 return item[property] as string; }; } parseDDMMYYYY(dateStr: string): Date | null { const dateParts = dateStr.split('-'); if (dateParts.length === 3) { return new Date(+dateParts[2], +dateParts[1] - 1, +dateParts[0]); } return null; } }
方案二:在matSortChange事件中手动处理排序
如果需要更灵活的控制,可以在排序变更事件中手动处理日期列的排序:
onSortChange(event: Sort) { const sortedData = [...this.dataSource.data]; if (event.active === 'date' && event.direction) { sortedData.sort((a, b) => { const dateA = this.parseDDMMYYYY(a.date); const dateB = this.parseDDMMYYYY(b.date); // 处理无效日期,这里默认把无效日期放在最后 if (!dateA) return 1; if (!dateB) return -1; return event.direction === 'asc' ? dateA.getTime() - dateB.getTime() : dateB.getTime() - dateA.getTime(); }); } else { // 非日期列的默认排序逻辑 sortedData.sort((x, y) => { const valX = x[event.active]; const valY = y[event.active]; return event.direction === 'asc' ? (valX < valY ? -1 : 1) : (valX > valY ? -1 : 1); }); } this.dataSource.data = sortedData; }
3. 模板部分(HTML)
确保mat-sort-header绑定的列名和TS中的字段名一致:
<table mat-table [dataSource]="dataSource" matSort #sort="matSort" (matSortChange)="onSortChange($event)"> <!-- 日期列 --> <ng-container matColumnDef="date"> <th mat-header-cell *matHeaderCellDef mat-sort-header>日期</th> <td mat-cell *matCellDef="let item">{{ item.date }}</td> </ng-container> <!-- 其他列示例 --> <ng-container matColumnDef="id"> <th mat-header-cell *matHeaderCellDef>ID</th> <td mat-cell *matCellDef="let item">{{ item.id }}</td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table>
注意事项
- 确保日期字符串格式严格为
dd-MM-yyyy,无多余空格或异常字符,否则解析函数会返回null。 - 若存在无效日期,可根据业务需求调整排序时的优先级(比如放在最前或最后)。
- 使用
getTime()将Date转为数字比较,比直接比较Date对象更稳定,避免部分浏览器的兼容性问题。
内容的提问来源于stack exchange,提问作者Asha A
相关产品推荐
相关产品推荐

