MatTable与Sort似乎没有对列进行排序

时间:2019-11-13 20:35:38

标签: angular typescript sorting angular-material

我正在使用一个简单的设计。在模块文件中,我添加了导入:MatSortModule和MatTableModule。在查看我创建的组件时,很简单:

<table mat-table [dataSource]="dataSource"
       matSort>
  <ng-container matColumnDef="interface"> <!-- vvv This area may have some importance vvv -->
    <th mat-header-cell *matHeaderCellDef mat-sort-header id="interface">Interface</th>
    <td mat-cell *matCellDef="let element"><span>{{element.interface}}</span></td>
  </ng-container>
  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>

,然后是TS文件:

class GridComponent {
    dataSource = null
    displayedColumns = ["interface"];
    @ViewChild(MatSort, {static: true}) sort: MatSort;
    @Input() set data(val: any[]) {
      this._data = val;
      getInfo();
    }
    get data () { return this._data; }
    private _data: any[];
    ngOnInit() {
      this.dataSource = new MatTableDataSource([])
      this.dataSource.sort = this.sort
    }

    getInfo() {
      this._service.get(this._data).subscribe( data => {
          /// For the ease of understanding. assume data is defined below.
          const arr = [{"interface":"foo"},{"interface":"bar"}]
          this.dataSource = new MatTableDataSource(arr)
          this.dataSource.sort = this.sort
      });
    }
}

网格将呈现所有行,并且切换按钮会显示等。当我切换它时,尽管信息不会重新排序。

我缺少什么吗?我看到一些样本,这些样本说我需要这样做:this.dataSource.sort = this.sort,但我真的不了解该目的以及它是否以某种方式干扰了排序机制。

在查看https://material.angular.io/components/sort/overview底部的编码示例时,我很困惑,因为我没有看到正在使用或分配给 mat-sort-header 的任何ID。属性,但在某些API中却声明要这么做

我希望澄清一下。

编辑:我正在寻找一个动态的答案,该答案可以让我轻松地更改数据源中的数据。现在,超出问题的范围,我有一个输入,可以更改与数据源关联的数据数组,因此,我正在努力以使其能够封装的方式进行处理,以便可以处理除组件。

2 个答案:

答案 0 :(得分:0)

是的,为了使排序适用于Mat数据表,您需要在ngOnInit()中使用this.dataSource.sort = this.sort

ngOnInit() {
    this.dataSource = new MatTableDataSource<FooModel>(foobar);
                this.dataSource.paginator = this.paginator;
                this.dataSource.sort = this.sort;
}

请注意如何从服务订阅中更新数据源:

    this.fooService.getFoobar(this.isFoo).subscribe((foobar: Foo[]) => {
              if (foobars != null) {
                this.dataSource = new MatTableDataSource<Foo>(foobar);
                this.dataSource.sort = this.sort;

答案 1 :(得分:0)

matSort有一个内置的更改,您可以捕获它来处理排序。这绕过了this.dataSource.sort = this.sort;行。因此,您可以删掉所有代码。

<table mat-table 
       [dataSource]="dataSource" 
       matSort 
       (matSortChange)="sortData($event)"></table>

,然后在代码中可以放置:

sortData(sort: Sort){
  // Sort sorts the current list, but it wasnt updating it unless i reassigned.
  this.dataSource.data = this.dataSource.data.sort((a, b) => {
    const isAsc = sort.direction === 'asc';
    return this._compare(a[sort.active], b[sort.active], isAsc);
  });
}
private _compare(a: number | string, b: number | string, isAsc: boolean) {
  return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}

另一个答案对我来说根本没有用,但现在一切顺利。

由于sort.direction,'asc','desc'和''共有3种状态,因此对于空字符串,我将数据源设置为等于原始列表顺序。

这里是修改后的组件,带有注释掉的区域现在可以删除

class GridComponent {
    /// Initialize the datasource we will be augmenting its inner data.
    dataSource: MatTableDataSource<any> = new MatTableDataSource();
    displayedColumns = ["interface"];
    //@ViewChild(MatSort, {static: true}) sort: MatSort;
    @Input() set data(val: any[]) {
      this._data = val;
      getInfo();
    }
    get data () { return this._data; }
    private _data: any[];
    ngOnInit() {
      //this.dataSource = new MatTableDataSource([])
      //this.dataSource.sort = this.sort
    }

    getInfo() {
      this._service.get(this._data).subscribe( data => {
          /// For the ease of understanding. assume data is defined below.
          const arr = [{"interface":"foo"},{"interface":"bar"}]
          /// Updated the below line to just update data.
          this.dataSource.data = arr;
          //this.dataSource.sort = this.sort
      });
    }
    sortData(sort: Sort){
      // Sort sorts the current list, but it wasnt updating it unless i reassigned.
      this.dataSource.data = this.dataSource.data.sort((a, b) => {
        const isAsc = sort.direction === 'asc';
        return this._compare(a[sort.active], b[sort.active], isAsc);
      });
    }
    private _compare(a: number | string, b: number | string, isAsc: boolean) {
      return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
    }
}