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();
}
我可能是愚蠢的,但据我所知,下面的代码应该完全遵循 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();
}