MatSort 与字母顺序与 Unicode 顺序不同的语言的排序规则?

问题描述 投票:0回答:2

在挪威语和丹麦语字母表中,挪威语/丹麦语字符的正确顺序是:

  1. Æ
  2. Ø
  3. Å

但是,MatSort 对这些字符使用 Unicode 顺序:

  1. (197)
  2. Æ (198)
  3. Ø (216)

可以通过某种方式实现排序来解决这个问题吗?

这是一个 stackblitz,其中有一个可以按“否”排序的表格。和“姓名”:

https://stackblitz.com/edit/angular-an1uqc-8mdqns

表中数据如下:

 {position: 1, name: 'Alpha', description: 'Test123'},
  {position: 2, name: 'Bravo',  description: '0'},
  {position: 3, name: 'Charlie', description: 'aaa'},
  {position: 4, name: 'Delta',  description: ''},
  {position: 5, name: 'Echo',  description: '1'},
  {position: 6, name: 'Foxtrot',  description: '2'},
  {position: 7, name: 'ÆGamma',  description: ''},
  {position: 8, name: 'ØHotel',  description: '3'},
  {position: 9, name: 'ÅIndigo',  description: '1000'},

];

根据挪威/丹麦字母表对最后三个项目(ÆGamma、ØHotel 和 ÅIndigo)进行排序的正确方法是:

  1. Æ伽玛
  2. Ø酒店
  3. Å靛蓝

但是 MatSort 使用这些字符的 Unicode 数字并按如下方式排序:

  1. Å靛蓝 (197)
  2. Æ伽玛 (198)
  3. Ø酒店 (216)

感谢您的阅读! :]

angular typescript sorting angular-material collation
2个回答
2
投票

您需要使用 matSortChange 来实现自定义排序,在本例中为本地化排序。这可以使用 String.prototype.localCompare 和语言标识符

da-DK
:

来完成

模板:

<table
  mat-table [dataSource]="sortedData"
  matSort (matSortChange)="sortData($event)"
  class="mat-elevation-z8">

成分:

sortData(sort: Sort) {
  const data = ELEMENT_DATA.slice();
  if (!sort.active || sort.direction === '') {
    this.sortedData = data;
    return;
  }

  this.sortedData = data.sort((a, b) => {
    const isAsc = sort.direction === 'asc';
    switch (sort.active) {
      case 'position': return compareNumber(a.position, b.position, isAsc);
      case 'name': return compareString(a.name, b.name, isAsc);
      case 'description': return compareString(a.description, b.description, isAsc);
      default: return 0;
    }
  });
}

// ...

function compareNumber(a: number, b: number, isAsc: boolean) {
  return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}

function compareString(a: string, b: string, isAsc: boolean) {
  return a.localeCompare(b, 'da-DK') * (isAsc ? 1 : -1);
}

这是一个正在运行的示例

排序结果如下:

1 Alpha
// ...
6 Foxtrot
7 ÆGamma
8 ØHotel
9 ÅIndigo

然后反过来:

9 ÅIndigo
8 ØHotel
7 ÆGamma
6 Foxtrot
// ...
1 Alpha

希望有帮助!


0
投票

我在使用德语变音符号时遇到了同样的问题。我使用 MatTableDataSource 的解决方案只是定义一个自定义 sortData() 实现:

@ViewChildren(MatSort) public matSortQueryList: QueryList<MatSort>;

public dataSource: MatTableDataSource<CUSTOMTYPE> = new MatTableDataSource<CUSTOMTYPE>([]);
private readonly defColl = new Intl.Collator('de');
private readonly _subs = new Subscription();

public ngAfterViewInit() {
  this.dataSource.data = CUSTOMDATA[];
  
  this._subs.add(
    this.matSortQueryList.changes.subscribe(elems => {
      if (elems.length && !this.dataSource.sort) {
        this.dataSource.sort = elems.first;
      }
    })
  );
  
  this.dataSource.sortData = (data: CUSTOMTYPE[], sort: MatSort) => {
    const sorted = data.sort((a, b) => {
      return this.defColl.compare(a.CUSTOMPROPERTY as string, b.CUSTOMPROPERTY as string);
    });

    return sort.direction === 'desc' ? sorted.reverse() : sorted;
  }
}

此外,我建议使用 Intl.Collator - 它比 localeCompare 快得多。

© www.soinside.com 2019 - 2024. All rights reserved.