首页 文章

Angular Material 2 DataTable使用嵌套对象进行排序

提问于
浏览
21

我有一个带有排序 Headers 的普通Angular Material 2 DataTable . 所有类型都是 Headers 工作正常 . 除了具有对象作为值的那个 . 这些根本不排序 .

例如:

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

注意 element.project.name

这是displayColumn配置:

displayedColumns = ['project.name', 'position', 'name', 'test', 'symbol'];

'project.name' 更改为 'project' 不起作用也 "project['name']"

我错过了什么?这有可能吗?

这是一个Stackblitz:Angular Material2 DataTable sort objects

Edit: 感谢您的所有答案 . 我必须为每个新的嵌套属性添加一个switch语句 .

这是我的解决方案:(创建一个扩展MatTableDataSource的新DataSource不是必需的)

export class NestedObjectsDataSource extends MatTableDataSource<MyObjectType> {

  sortingDataAccessor: ((data: WorkingHours, sortHeaderId: string) => string | number) =
    (data: WorkingHours, sortHeaderId: string): string | number => {
      let value = null;
      if (sortHeaderId.indexOf('.') !== -1) {
        const ids = sortHeaderId.split('.');
        value = data[ids[0]][ids[1]];
      } else {
        value = data[sortHeaderId];
      }
      return _isNumberValue(value) ? Number(value) : value;
    }

  constructor() {
    super();
  }
}

7 回答

  • -1

    我为多个嵌套对象级别定制 .

    this.dataSource.sortingDataAccessor =
      (data: any, sortHeaderId: string): string | number => {
        let value = null;
        if (sortHeaderId.includes('.')) {
          const ids = sortHeaderId.split('.');
          value = data;
          ids.forEach(function (x) {
            value = value? value[x]: null;
          });
        } else {
          value = data[sortHeaderId];
        }
        return _isNumberValue(value) ? Number(value) : value;
      };
    
  • 10

    我有同样的问题,通过测试我遇到一些错误的第一个命题,我可以通过添加“switch(property)”修复它

    this.dataSource.sortingDataAccessor =(item, property) => {
        switch (property) {
        case 'project.name': return item.project.name;
    
        default: return item[property];
        }
      };
    
  • 1

    它试图按元素['project.name']排序 . 显然元素没有这样的属性 .

    创建一个扩展MatTableDatasource并支持嵌套对象属性排序的自定义数据源应该很容易 . 查看有关使用自定义源的material.angular.io文档中的示例 .

  • 35

    只要您对字段使用点表示法,甚至可以缩短给出的答案,不需要切换 .

    ngOnInit() {
      this.dataSource = new MatTableDataSource(yourData);
    
      this.dataSource.sortingDataAccessor = (item, property) => {
         if (property.includes('.')) return property.split('.').reduce((o,i)=>o[i], item)
         return item[property];
      };
    
      this.dataSource.sort = sort;
    }
    
  • 0

    很难找到关于此的文档,但可以使用 sortingDataAccessor 和switch语句 . 例如:

    @ViewChild(MatSort) sort: MatSort;
    
    ngOnInit() {
      this.dataSource = new MatTableDataSource(yourData);
      this.dataSource.sortingDataAccessor = (item, property) => {
        switch(property) {
          case 'project.name': return item.project.name;
          default: return item[property];
        }
      };
      this.dataSource.sort = sort;
    }
    
  • 0

    您可以在组件中编写一个函数来从对象获取深层属性 . 然后在 dataSource.sortingDataAccessor 中使用它,如下所示

    getProperty = (obj, path) => (
      path.split('.').reduce((o, p) => o && o[p], obj)
    )
    
    ngOnInit() {
      this.dataSource = new MatTableDataSource(yourData);
      this.dataSource.sortingDataAccessor = (obj, property) => this.getProperty(obj, property);
      this.dataSource.sort = sort;
    }
    
    columnDefs = [
      {name: 'project.name', title: 'Project Name'},
      {name: 'position', title: 'Position'},
      {name: 'name', title: 'Name'},
      {name: 'test', title: 'Test'},
      {name: 'symbol', title: 'Symbol'}
    ];
    

    并在HTML中

    <ng-container *ngFor="let col of columnDefs" [matColumnDef]="col.name">
          <mat-header-cell *matHeaderCellDef>{{ col.title }}</mat-header-cell>
          <mat-cell *matCellDef="let row">
            {{ getProperty(row, col.name) }}
          </mat-cell>
      </ng-container>
    
  • 0

    我使用通用方法,允许您使用带有 mat-sort-headermatColumnDef 的dot.seperated.path . 如果无法找到路径指定的属性,则无法以静默方式返回undefined .

    function pathDataAccessor(item: any, path: string): any {
      return path.split('.')
        .reduce((accumulator: any, key: string) => {
          return accumulator ? accumulator[key] : undefined;
        }, item);
    }
    

    您只需要设置数据访问器

    this.dataSource.sortingDataAccessor = pathDataAccessor;
    

相关问题