如何在Angular 5 Material表格中实现matSort功能
实现MatSort表头排序功能
看起来你已经搞定了表格数据渲染,现在要加排序功能对吧?我来一步步帮你实现,分两种方案——一种是基于你现有的自定义UserDataSource,另一种是用Angular Material提供的MatTableDataSource(更简单),你可以根据自己的需求选。
第一步:确保模块已导入
首先得保证你的Angular模块里导入了必要的Material组件和动画模块,不然排序功能没法生效。在你的组件所在的Module(比如AppModule或者UserTableModule)里添加这些导入:
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { MatTableModule } from '@angular/material/table'; import { MatSortModule } from '@angular/material/sort'; import { HttpClientModule } from '@angular/common/http'; @NgModule({ imports: [ // ...其他已有的导入 BrowserAnimationsModule, // Material组件必须依赖这个 MatTableModule, MatSortModule, HttpClientModule ] }) export class YourModule { }
第二步:修改模板,添加排序指令
接下来要给你的表格和表头加上排序相关的指令:
- 在
<table mat-table>标签上绑定[matSort]="sort",关联组件里的MatSort实例 - 给每个
<th mat-header-cell>添加mat-sort-header指令,这样点击表头就能触发排序
修改后的模板代码大概是这样:
<table mat-table [dataSource]="dataSource" [matSort]="sort" class="mat-elevation-z8"> <!-- Name列 --> <ng-container matColumnDef="name"> <th mat-header-cell *matHeaderCellDef mat-sort-header> 姓名 </th> <td mat-cell *matCellDef="let user"> {{user.name}} </td> </ng-container> <!-- Email列 --> <ng-container matColumnDef="email"> <th mat-header-cell *matHeaderCellDef mat-sort-header> 邮箱 </th> <td mat-cell *matCellDef="let user"> {{user.email}} </td> </ng-container> <!-- Phone列 --> <ng-container matColumnDef="phone"> <th mat-header-cell *matHeaderCellDef mat-sort-header> 电话 </th> <td mat-cell *matCellDef="let user"> {{user.phone}} </td> </ng-container> <!-- Company列 --> <ng-container matColumnDef="company"> <th mat-header-cell *matHeaderCellDef mat-sort-header> 公司 </th> <td mat-cell *matCellDef="let user"> {{user.company.name}} </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table>
方案一:基于你现有的自定义UserDataSource
如果想继续用你自己的UserDataSource,需要修改数据源类,让它支持监听排序变化并对数据进行排序:
1. 更新UserDataSource类
import { DataSource } from '@angular/cdk/collections'; import { Observable, BehaviorSubject } from 'rxjs'; import { User } from './user.model'; import { UserService } from './user.service'; import { MatSort } from '@angular/material/sort'; export class UserDataSource extends DataSource<User> { private usersSubject = new BehaviorSubject<User[]>([]); private sortInstance: MatSort | undefined; constructor(private userService: UserService) { super(); this.loadInitialUsers(); } // 连接表格,返回数据Observable connect(): Observable<User[]> { return this.usersSubject.asObservable(); } disconnect(): void { this.usersSubject.complete(); } // 设置排序实例,并监听排序变化 setSort(sort: MatSort): void { this.sortInstance = sort; // 当排序条件改变时,重新加载并排序数据 this.sortInstance.sortChange.subscribe(() => this.loadInitialUsers()); } // 加载用户数据并排序 private loadInitialUsers(): void { this.userService.getUser().subscribe(users => { const sortedUsers = this.sortUserList([...users]); this.usersSubject.next(sortedUsers); }); } // 根据当前排序条件对用户列表排序 private sortUserList(users: User[]): User[] { if (!this.sortInstance || !this.sortInstance.active || this.sortInstance.direction === '') { return users; } return users.sort((a, b) => { const isAscending = this.sortInstance.direction === 'asc'; switch (this.sortInstance.active) { case 'name': return compare(a.name, b.name, isAscending); case 'email': return compare(a.email, b.email, isAscending); case 'phone': return compare(a.phone, b.phone, isAscending); case 'company': // 处理嵌套的company.name属性 return compare(a.company.name, b.company.name, isAscending); default: return 0; } }); } } // 通用比较函数,支持字符串/数字排序 function compare(a: string | number, b: string | number, isAsc: boolean): number { return (a < b ? -1 : 1) * (isAsc ? 1 : -1); }
2. 在组件中绑定排序实例
修改你的UsertableComponent,在ngOnInit里把MatSort实例传给数据源:
import { Component, OnInit, ViewChild } from '@angular/core'; import { MatSort } from '@angular/material/sort'; import { UserDataSource } from './user-data-source'; import { UserService } from './user.service'; export class UsertableComponent implements OnInit { @ViewChild(MatSort) sort!: MatSort; dataSource: UserDataSource; displayedColumns = ['name', 'email', 'phone', 'company']; constructor(private userService: UserService) { this.dataSource = new UserDataSource(userService); } ngOnInit(): void { // 将排序实例传给数据源 this.dataSource.setSort(this.sort); } }
方案二:使用MatTableDataSource(更简单)
如果你不想维护自定义数据源,Angular Material提供的MatTableDataSource已经内置了排序支持,用起来更省心:
1. 修改组件代码
import { Component, OnInit, ViewChild } from '@angular/core'; import { MatSort } from '@angular/material/sort'; import { MatTableDataSource } from '@angular/material/table'; import { User } from './user.model'; import { UserService } from './user.service'; export class UsertableComponent implements OnInit { @ViewChild(MatSort) sort!: MatSort; dataSource = new MatTableDataSource<User>(); displayedColumns = ['name', 'email', 'phone', 'company']; constructor(private userService: UserService) { } ngOnInit(): void { this.userService.getUser().subscribe(users => { this.dataSource.data = users; // 绑定排序实例 this.dataSource.sort = this.sort; // 关键:处理嵌套的company.name属性排序 this.dataSource.sortingDataAccessor = (user, property) => { switch (property) { case 'company': return user.company.name; default: // 其他直接取属性值 return user[property as keyof User]; } }; }); } }
这种情况下,你不需要自定义UserDataSource,MatTableDataSource会自动处理排序逻辑,只需要通过sortingDataAccessor告诉它怎么获取嵌套属性的值就行。
这样设置完之后,点击表头就能看到排序效果了——第一次点击升序,第二次降序,第三次取消排序。
内容的提问来源于stack exchange,提问作者Umair Jameel
相关产品推荐
相关产品推荐

