Angular Material Table 排序行为导致顺序不正确

Angular Material Table sort behaving resulting in incorrect order

我可能是愚蠢的,但据我所知,下面的代码应该完全遵循 angular material 网站上的示例。但是,排序结果不正确。

我可以看到排序是因为顺序改变了。第 xxx50 行成为第一行。行 xxx01 移动到 xxx50 的原始位置。其余数据按原始顺序排列。 asc 和 des 结果相同。

请告诉我我做错了什么。

html:

<div class="mat-elevation-z8">
    <table mat-table [dataSource]="dataSource" matSort>
        <ng-container matColumnDef="agent">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Agent</th>
            <td mat-cell *matCellDef="let relationshipInterface"> {{relationshipInterface.agentDisplayName}} </td>
        </ng-container>
        <ng-container matColumnDef="player">
            <th mat-header-cell *matHeaderCellDef mat-sort-header>Player</th>
            <td mat-cell *matCellDef="let relationshipInterface"> {{relationshipInterface.playerDisplayName}} </td>
        </ng-container>
        <ng-container matColumnDef="avatar">
            <th mat-header-cell *matHeaderCellDef mat-sort-header>Nickname</th>
            <td mat-cell *matCellDef="let relationshipInterface"> {{relationshipInterface.avatarDisplayName}} </td>
        </ng-container>

        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;">
        </tr>
    </table>

    <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
</div>

ts:

import { Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator, MatSort, MatTableDataSource } from '@angular/material';

export interface RelationshipInterface {
  agentName: string;
  agentDisplayName: string;
  playerName: string;
  playerDisplayName: string;
  avatarName: string;
  avatarDisplayName: string;
}

@Component({
  selector: 'app-relationships-table',
  templateUrl: './relationships-table.component.html',
  styleUrls: ['./relationships-table.component.css']
})
export class RelationshipsTableComponent implements OnInit {
  displayedColumns: string[] = ['agent', 'player', 'avatar'];
  dataSource: MatTableDataSource<RelationshipInterface>;

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;

  constructor() {

  }

  ngOnInit() {
    this.dataSource = new MatTableDataSource(
      this.getTempData()
    );
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

  applyFilter(filterColumn: string, filterValue: any) {
  }

  getTempData() {
    const newData = [];
    for (let i = 0; i < 100; i++) {
      let str: string;
      if (i < 10) {
        str = '0' + i;
      } else {
        str = '' + i;
      }
      const relationshipInterface = {
        agentName: 'agent name ' + str,
        agentDisplayName: 'agent dName ' + str,
        playerName: 'player name ' + str,
        playerDisplayName: 'player dName ' + str,
        avatarName: 'avatar name ' + str,
        avatarDisplayName: 'avatar dName ' + str,
      };
      newData.push(relationshipInterface);
    }
    return newData;
  }
}

经过测试,显然,列名称必须与数据源 属性 名称匹配。

html:

<ng-container matColumnDef="agent">

ts:

export interface RelationshipInterface {
  agent: string; // was agentDisplayName
}

把它放在那里是因为它是 Google 上的第一篇文章。如果其他人遇到这个问题;

我的第一个问题是我排序的一些字符串的开头有白色 space。这导致进行了奇怪的排序。

第二个问题是 MatSort 区分大小写 (https://github.com/angular/components/issues/9205)。这意味着它首先对大字母进行排序,然后对小字母进行排序。列表 AbCd 将被排序为 ACbd。

解决方案:在将要排序的数据传递给排序功能之前,使用 sortingDataAccessor 对其进行操作。 string.trim() 删除字符串开头和结尾的白色 space 字符。然后它可以作为 string.toLowerCase() 返回,以确保所有数据的排序不区分大小写。

示例:

@ViewChild(MatSort, { static: false }) set content(sort: MatSort) {
    if (this.dataSource) {
      this.dataSource.sortingDataAccessor = (item, property) => {
        switch (property) {
          case 'description':
            return this.cleanData(item.description);
          case 'name':
            return this.cleanData(item.name);
          default:
            return item[property] || '';
        }
      };
      this.dataSource.sort = sort;
    }
  }

    private cleanData(sortString: string): string {
    let cleanString = '';
    if (sortString) {
      cleanString = sortString.trim();
    }
    return cleanString.toLowerCase();
  }