繁体   English   中英

Angular - 表格排序不适用于嵌套对象

[英]Angular - table sorting not working for nested objects

我有一个角度表,但日期排序不正确。 除了日期之外,其余列的排序非常好。 我认为这是因为日期是一个嵌套对象,我尝试使用 matSortChange() 但没有任何效果。

我在这里创建了一个演示: DEMO

 const ELEMENT_DATA: PeriodicElement[] = [
     {position: 1,
       name: 'A', 
       weight: 1.5079, 
       timeModel: {CreatedTime: "2020-04-30T15:38:11.186Z", LastModified: "2020-06-08T15:38:11.186Z"}
      },
       {position: 2,
       name: 'B', 
       weight: 1.4079, 
       timeModel: {CreatedTime: "2021-03-30T15:38:11.186Z", LastModified: "2020-06-10T15:38:11.186Z"}
      },
       {position: 3,
       name: 'C', 
       weight: 1.3079, 
       timeModel: {CreatedTime: "2020-01-30T15:38:11.186Z", LastModified: "2020-03-30T15:38:11.186Z"}
      },
    ];

我确实尝试添加一个自定义排序函数来尝试对日期进行排序,但它无法正常工作。

   public changeSort(event: Event) {

     if (event.active === 'date') {   
       this.dataSource.filteredData = this.dataSource.filteredData.sort(function(a, b) {
      return new Date(a.timeModel.CreatedTime).getTime() - new Date(b.timeModel.CreatedTime).getTime();
    });
    }

  }

HTML

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

  <!-- Position Column -->
  <ng-container matColumnDef="position">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> No. </th>
    <td mat-cell *matCellDef="let element"> {{element.position}} </td>
  </ng-container>

  <!-- Name Column -->
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
    <td mat-cell *matCellDef="let element"> {{element.name}} </td>
  </ng-container>

  <!-- Weight Column -->
  <ng-container matColumnDef="weight">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> Weight </th>
    <td mat-cell *matCellDef="let element"> {{element.weight}} </td>
  </ng-container>

  <!-- Symbol Column -->
  <ng-container matColumnDef="date">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> Date </th>
    <td mat-cell *matCellDef="let element"> {{element.timeModel.CreatedTime}} </td>
  </ng-container>

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

} 

是的,问题是因为它是一个对象。 matColumnDef="weight"描述了要纳入排序功能的属性。 所以从这个对象:

{
  position: 1,
  name: 'A', 
  weight: 1.5079, 
  timeModel: {CreatedTime: "2020-04-30T15:38:11.186Z", LastModified: "2020-06-08T15:38:11.186Z"}
}

weight被采取。 但是matColumnDef="date"结果只是undefined - 您的对象中没有属性date

因此,如果可能,请更改 dataSource 对象并仅提供它需要的日期(因为您似乎只在表中使用CreatedTime )。

您还可以覆盖sortingDataAccessor 函数,它最初看起来像这样的 atm:

sortingDataAccessor: ((data: T, sortHeaderId: string) => string|number) =
    (data: T, sortHeaderId: string): string|number => {
  const value = (data as {[key: string]: any})[sortHeaderId];

  if (_isNumberValue(value)) {
    const numberValue = Number(value);
    return numberValue < MAX_SAFE_INTEGER ? numberValue : value;
  }

  return value;
}

您需要添加一个条件来查看当前的sortHeaderId值是否为'date' 然后告诉它如何获取要在排序函数中使用的对象所需的值:

this.dataSource.sortingDataAccessor = (data, sortHeaderId) => {
  const value = (data as {[key: string]: any})[sortHeaderId];
  
  const MAX_SAFE_INTEGER = 9007199254740991;

  if (_isNumberValue(value)) {
    const numberValue = Number(value);    
    return numberValue < MAX_SAFE_INTEGER ? numberValue : value;
  }

  if (sortHeaderId === 'date') {
    return new Date(data.timeModel.CreatedTime)
  }

  return value;
}

ps 如果想保留该功能,您需要从 Angular 导入MAX_SAFE_INTEGER_isNumberValue

我可以在您的代码中检测到一些问题:

  1. 你所有的日期都是一样的,所以没有排序会影响它。
  2. 你进入了函数changeSort一个 if 语句if(event.direction === "desc") ,尝试将其更改为if(event.active === "date") ,其他排序工作正常,你想要排除此条件仅对日期排序。

看起来 Angular 不知道应该排序的属性的正确方法。 因此,我们可以使用自定义排序数据访问器将其显示给 Angular:

public changeSort(event: Event) {
    console.log(event)
    this.dataSource.sortingDataAccessor = (item, property) => {
        switch (property) {
            case 'date': return item.timeModel.CreatedTime;
            default: return item[property];
        }
    };
}

一个完整的 stackblitz 示例可以在这里看到

将 unix 时间戳存储为数据并在屏幕上显示时对其进行格式化。 这样您就不需要创建排序函数。

这是一个工作示例https://stackblitz.com/edit/angular-j7ycna-wdvvnw

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM