You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:17:12