【问题标题】:Mat-table Sorting Demo not Working垫表排序演示不工作
【发布时间】:2017-10-23 15:33:05
【问题描述】:

我正在尝试让 mat-table 排序在本地工作,虽然我可以让数据按预期显示,但单击标题行不会像在在线示例中那样进行排序(在全部)。 我试图让这个演示在本地工作: https://material.angular.io/components/sort/overview https://plnkr.co/edit/XF5VxOSEBxMTd9Yb3ZLA?p=preview

我使用 Angular CLI 生成了一个新项目,然后按照以下步骤操作: https://material.angular.io/guide/getting-started

这是我的本地文件:

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { MatSort, MatTableModule } from '@angular/material';

import { AppComponent } from './app.component';
import { TableSortingExample } from './table-sorting-example';

@NgModule({
  declarations: [
    AppComponent,
    TableSortingExample,
    MatSort
  ],
  imports: [
    BrowserModule,
    MatTableModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';
}

app.component.html

<div style="text-align:center">
  <h1>
    Welcome to {{title}}!
  </h1>
  <table-sorting-example></table-sorting-example>
</div>

table-sorting-example.html

<div class="example-container mat-elevation-z8">
  <mat-table #table [dataSource]="dataSource" matSort>

    <!--- Note that these columns can be defined in any order.
          The actual rendered columns are set as a property on the row definition" -->

    <!-- ID Column -->
    <ng-container matColumnDef="userId">
      <mat-header-cell *matHeaderCellDef mat-sort-header> ID </mat-header-cell>
      <mat-cell *matCellDef="let row"> {{row.id}} </mat-cell>
    </ng-container>

    <!-- Progress Column -->
    <ng-container matColumnDef="progress">
      <mat-header-cell *matHeaderCellDef mat-sort-header> Progress </mat-header-cell>
      <mat-cell *matCellDef="let row"> {{row.progress}}% </mat-cell>
    </ng-container>

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

    <!-- Color Column -->
    <ng-container matColumnDef="color">
      <mat-header-cell *matHeaderCellDef mat-sort-header> Color </mat-header-cell>
      <mat-cell *matCellDef="let row" [style.color]="row.color"> {{row.color}} </mat-cell>
    </ng-container>

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


<!-- Copyright 2017 Google Inc. All Rights Reserved.
    Use of this source code is governed by an MIT-style license that
    can be found in the LICENSE file at http://angular.io/license -->

table-sorting-example.ts

import {Component, ViewChild} from '@angular/core';
import {DataSource} from '@angular/cdk/collections';
import {MatSort} from '@angular/material';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';

/**
 * @title Table with sorting
 */
@Component({
  selector: 'table-sorting-example',
  styleUrls: ['table-sorting-example.css'],
  templateUrl: 'table-sorting-example.html',
})
export class TableSortingExample {
  displayedColumns = ['userId', 'userName', 'progress', 'color'];
  exampleDatabase = new ExampleDatabase();
  dataSource: ExampleDataSource | null;

  @ViewChild(MatSort) sort: MatSort;

  ngOnInit() {
    this.dataSource = new ExampleDataSource(this.exampleDatabase, this.sort);
  }
}

/** Constants used to fill up our data base. */
const COLORS = ['maroon', 'red', 'orange', 'yellow', 'olive', 'green', 'purple',
  'fuchsia', 'lime', 'teal', 'aqua', 'blue', 'navy', 'black', 'gray'];
const NAMES = ['Maia', 'Asher', 'Olivia', 'Atticus', 'Amelia', 'Jack',
  'Charlotte', 'Theodore', 'Isla', 'Oliver', 'Isabella', 'Jasper',
  'Cora', 'Levi', 'Violet', 'Arthur', 'Mia', 'Thomas', 'Elizabeth'];

export interface UserData {
  id: string;
  name: string;
  progress: string;
  color: string;
}

/** An example database that the data source uses to retrieve data for the table. */
export class ExampleDatabase {
  /** Stream that emits whenever the data has been modified. */
  dataChange: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>([]);
  get data(): UserData[] { return this.dataChange.value; }

  constructor() {
    // Fill up the database with 100 users.
    for (let i = 0; i < 100; i++) { this.addUser(); }
  }

  /** Adds a new user to the database. */
  addUser() {
    const copiedData = this.data.slice();
    copiedData.push(this.createNewUser());
    this.dataChange.next(copiedData);
  }

  /** Builds and returns a new User. */
  private createNewUser() {
    const name =
      NAMES[Math.round(Math.random() * (NAMES.length - 1))] + ' ' +
      NAMES[Math.round(Math.random() * (NAMES.length - 1))].charAt(0) + '.';

    return {
      id: (this.data.length + 1).toString(),
      name: name,
      progress: Math.round(Math.random() * 100).toString(),
      color: COLORS[Math.round(Math.random() * (COLORS.length - 1))]
    };
  }
}

/**
 * Data source to provide what data should be rendered in the table. Note that the data source
 * can retrieve its data in any way. In this case, the data source is provided a reference
 * to a common data base, ExampleDatabase. It is not the data source's responsibility to manage
 * the underlying data. Instead, it only needs to take the data and send the table exactly what
 * should be rendered.
 */
export class ExampleDataSource extends DataSource<any> {
  constructor(private _exampleDatabase: ExampleDatabase, private _sort: MatSort) {
    super();
  }

  /** Connect function called by the table to retrieve one stream containing the data to render. */
  connect(): Observable<UserData[]> {
    const displayDataChanges = [
      this._exampleDatabase.dataChange,
      this._sort.sortChange,
    ];

    return Observable.merge(...displayDataChanges).map(() => {
      return this.getSortedData();
    });
  }

  disconnect() {}

  /** Returns a sorted copy of the database data. */
  getSortedData(): UserData[] {
    const data = this._exampleDatabase.data.slice();
    if (!this._sort.active || this._sort.direction == '') { return data; }

    return data.sort((a, b) => {
      let propertyA: number|string = '';
      let propertyB: number|string = '';

      switch (this._sort.active) {
        case 'userId': [propertyA, propertyB] = [a.id, b.id]; break;
        case 'userName': [propertyA, propertyB] = [a.name, b.name]; break;
        case 'progress': [propertyA, propertyB] = [a.progress, b.progress]; break;
        case 'color': [propertyA, propertyB] = [a.color, b.color]; break;
      }

      let valueA = isNaN(+propertyA) ? propertyA : +propertyA;
      let valueB = isNaN(+propertyB) ? propertyB : +propertyB;

      return (valueA < valueB ? -1 : 1) * (this._sort.direction == 'asc' ? 1 : -1);
    });
  }
}


/**  Copyright 2017 Google Inc. All Rights Reserved.
 Use of this source code is governed by an MIT-style license that
 can be found in the LICENSE file at http://angular.io/license */

有没有人知道为什么它会像在线表格一样显示但缺少排序功能?

【问题讨论】:

  • 我会先调试应用程序。有什么错误吗?运行ng test --sm=false 看看会发生什么。
  • 没有@ViewChild(MatSort) sort: MatSort; 对我有用有什么原因吗?

标签: angular angular-material


【解决方案1】:

对于可能遇到此问题的其他人: 问题是我没有在角度材料网站上正确阅读 API 参考,这部分说我必须导入 MatSortModule。在我将 app.module.ts 中的导入列表更改为

之后
imports: [
    BrowserModule,
    MatTableModule,
    MatSortModule
  ],

效果很好

【讨论】:

  • 文档中没有提到这个模块。 material.angular.io/components/table/overview#sorting我也浪费了一个小时。
  • 这很好,在标题文本是可点击的,图标也在那里,但仍然无法排序。
  • 检查BrowserAnimationsModule是否也导入app.module.ts
  • 我可以说他们是 SOB 吗?我花了 1 小时试图弄清楚为什么我的 ViewChild 不工作。他们不能从 MatTableModule 导入/导出这个 MatSortModule 吗??
  • 我已经导入了 MatSortModuleBrowserAnimationsModule,并且我已经确保 matColumnDef 值与属性名称匹配,但我仍然无法让它做任何事情。跨度>
【解决方案2】:

我遇到了一个问题,即排序功能正常工作,但排序不正确。我意识到matColumnDef 必须与我在matCellDef 中引用的class / interface 的属性名称相同。

根据Angular材质documentation

默认情况下,MatTableDataSource 排序时假设已排序列的名称与列显示的数据属性名称匹配。

例如:

<ng-container matColumnDef="name"> 
    <mat-header-cell *matHeaderCellDef mat-sort-header> NAME </mat-header-cell>
    <mat-cell *matCellDef="let row"> {{row.name}} </mat-cell>
</ng-container>

matColumnDef 指令中的name 必须与&lt;mat-cell&gt; 组件中使用的name 相同。

【讨论】:

  • 您在示例中引用了什么?查看您的界面以进行比较也会很有帮助。
  • 我使用“Id”作为列名,而实体使用“id”。案例的不同是使它无法运行(由于重构失误)。现在它已解决。谢谢
  • @NitinSingh,如果你需要在element 上调用一个函数,像这样` {{row.getName()}} `
  • 天哪。这是一种……奇怪的处理方式。虽然为我工作!花了一个小时试图找出问题所在,谢谢!
【解决方案3】:

如果表在 *ngIf 中,它将无法工作。 改成[隐藏]就可以了

【讨论】:

  • !!!你拯救了我的一天!!!使用 &lt;div [hidden]="!xxx"&gt; 代替 &lt;div *ngIf="xxx"&gt;
  • 或者只是在ngAfterViewInit中设置数据源而不是ngOnInit
  • 这是可能发生的最“隐藏”的问题,感谢您的解决方案!文档可能会对此提出警告
  • 该解决方案对我有用。谢谢@aungye,但是,只是想知道是什么触发了 *ngIf 的这个问题,有什么想法吗?
  • 当接受的答案不适合您时,我会说继续向下滚动。这真的节省了我的一天!
【解决方案4】:

matColumnDef 名称和 *matCellDef 实际值名称应该相同

例子:

<ng-container matColumnDef="oppNo">
    <th mat-header-cell *matHeaderCellDef mat-sort-header>Opportunity Number</th>
    <td mat-cell *matCellDef="let element">{{element.oppNo}}</td>
</ng-container>

在我的情况下,matColumnDef 名称和 *matCellDef 名称的 oppNo 相同,并且排序工作正常。

【讨论】:

  • 有趣。我也是这样。但是,你知道这个或那个背后的实际原因实际上是某种“错误”吗?
  • 我发现,原因是,它需要数据源中的这个键来排序。所以它不需要像 matCellDef 那样是 1to1 的,但是你需要在 dataSource 内部有一个引用属性。
【解决方案5】:

我也遇到了这个问题。由于需要等待孩子被定义,所以必须实现和使用AfterViewInit,而不是onInit。

  ngAfterViewInit (){
    this.dataSource.sort = this.sort;
  }

【讨论】:

  • 我正在使用带有排序、过滤和分页功能的表格。您是否知道为什么只需要在 ngAfterViewInit 中定义排序?其余的工作来自ngOnInit。只是想了解一下,多亏你解决了
  • @NicolasM。 this.sort 字段通过 @ViewChild 注释绑定,此类字段在 ngAfterViewInit 中实例化,但尚未在 ngOnInit 中实例化
  • 非常感谢@flashape,这行得通
【解决方案6】:

MatSort 可能不起作用的原因之一是它在定义之前被添加到数据源(即this.dataSource.sort = this.sort)。这可能有多种原因:

  1. 如果你在 ngOnInit 中添加排序。此时模板尚未呈现,因此您使用 @ViewChild(MatSort, { static: true }) sort: MatSort; 获得的 MatSort 是未定义的,可以理解的是不会做任何事情。此问题的解决方案是将this.dataSource.sort = sort 移至ngAfterViewInit。当调用 ngAfterViewInit 时,您的组件会被渲染,并且应该定义 MatSort。

  2. 当您使用 *ngIf 时,您的表格元素是您的模板,或者如果它是父元素,则此 *ngIf 会导致您的表格在您尝试设置 MatSort 时不被渲染。例如,如果您的表格元素上有*ngIf="dataSource.data.length &gt; 0"(仅在存在数据时才呈现它)并且您在使用数据设置this.dataSource.data 之后立即设置this.dataSource.sort = this.sort。组件视图还不会被重新渲染,所以 MatSort 仍然是未定义的。

为了让 MatSort 工作并仍然有条件地显示您的表格,您可以决定将 *ngIf 替换为 [hidden],如多个其他答案中所述。但是,如果要保留 *ngIf 语句,可以使用以下解决方案。这个解决方案适用于 Angular 9,我没有在以前的版本上测试过,所以我不确定它是否在那里工作。

我在这里找到了这个解决方案:https://github.com/angular/components/issues/10205

而不是放:

@ViewChild(MatSort) sort: MatSort;

对 matSort 使用 setter。一旦您的视图中的 matSort 发生更改(即第一次定义),此设置器将触发,当您通过单击箭头更改排序时,它不会触发。这将如下所示:

@ViewChild(MatSort) set matSort(sort: MatSort) {
    this.dataSource.sort = sort;
}

如果您有其他功能(以编程方式)更改排序,我不确定它是否会再次触发,我还没有测试过。如果您不想确保它仅在未定义排序时设置排序,您可以执行以下操作:

@ViewChild(MatSort) set matSort(sort: MatSort) {
    if (!this.dataSource.sort) {
        this.dataSource.sort = sort;
    }
}

【讨论】:

  • 谢谢,这个解决方案很完美。请注意,如果您的表有 *ngIf(例如,等待来自 API 的数据),则需要添加条件来检查“排序”是否存在。如果不这样做,您将在控制台上收到错误“无法设置未定义的属性'排序'”。
  • 这个解决方案似乎对我有用,但是在检查模板中的表上是否存在排序后,我仍然遇到控制台错误。
  • 完美答案。为我工作
【解决方案7】:

在超时块中添加排序对我有用,

dataSource = new MatTableDataSource(this.articleService.getAllArticles());
setTimeout(() => {
  this.tableDataSource.sort = this.sort;
  this.tableDataSource.paginator = this.paginator;
});

如果您不想使用生命周期钩子。

【讨论】:

  • 愚蠢的 hack,但它可以工作,知道为什么没有超时它就不能工作吗?
  • 确实是一种糟糕的做法。它之所以起作用,是因为您在组件初始化之后让一些时间过去,以便构建数据源,然后添加排序和分页器。最好的办法是在 ngOnInit 中移动 datSource 构建,然后在 AfterViewInit 中移动排序和分页器分配。这就是生命周期钩子存在的目的。
【解决方案8】:

我在这个问题上花了几个小时。在阅读了许多线程之后,这是我所做的步骤。

  1. 作为@avern mentioned,需要导入MatSortModule
  2. 确保您将表格包含在*ngIf 中。将其更改为 [hidden]@zerg recommended。 (我不明白为什么)

希望这会有所帮助。

【讨论】:

  • 它浪费了我一天的时间来找出问题,愚蠢的没有显示任何错误。
【解决方案9】:

我的解决方案是修复几个问题(基本上合并了此页面中的大多数解决方案)。

检查事项:

  1. BrowserModule, MatTableModule, MatSortModule 模块应该导入到根模块文件中。
  2. 确保已使用MatTableDatasource 类并将您的数据数组作为参数传入其中
  3. 确保您的表没有嵌套在*ngIf=.... 指令中。改用其他条件操作(还是不明白为什么)。

【讨论】:

    【解决方案10】:

    在您的 app.module.ts 中,执行以下操作:

    导入

    import { MatSortModule } from '@angular/material/sort';
    

    然后添加

    imports: [
        ...
        MatSortModule
    ],
    

    【讨论】:

    • 非常感谢,真是糟糕的体验...
    【解决方案11】:

    我通过将表数据命名为与 *matColumnDef 相同的名称来解决此问题 例如:

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

    相反

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

    【讨论】:

    • 这帮助我解决了这个问题。然而,事实证明它也是区分大小写的。所以 matColumnDef="name" 也必须匹配 row.name 的大小写。
    【解决方案12】:

    对我来说有 2 个问题。

    1. matColumnDef 和 matCellDef -> 名称不同
    2. 我从服务中获取数据。 ngOnInit 排序不起作用。替换为

      ngAfterViewInit() { this.dataSource.sort = this.sort; }

    【讨论】:

      【解决方案13】:

      我发现这个旧博客帮助我让它工作: https://www.jeffryhouser.com/index.cfm/2018/10/23/Five-Reasons-My-ngMaterial-Table-wont-sort

      1. 确保导入MatSortModule
      2. 指定matSort 标头
      3. 确保将数据源包装在 MatTableDataSource
        • 这是帮助我整理出来的那个(明白了吗?整理)。在模板中,我直接引用了数组 (&lt;table mat-table [dataSource]="this.products" matSort&gt;),但我应该使用在代码中初始化的数据源对象 (&lt;table mat-table [dataSource]="this.dataSource" matSort&gt;)。数据源初始化为dataSource = new MatTableDataSource(this.products)
      4. 告诉数据源你的排序,ngOnInit/ngAfterViewInit
      5. 编写自己的排序,如果您不想使用MatTableDataSource

      【讨论】:

        【解决方案14】:

        对于那些对这些命名必须相等感到困惑的人,我做了一些测试:

        这将起作用(属性的名称与列def相同):

        <ng-container matColumnDef="version">
            <th mat-header-cell *matHeaderCellDef mat-sort-header> Version </th>
            <td mat-cell *matCellDef="let element"> {{element.version}} </td>
        </ng-container>
        
        displayedColumns: string[] = ['version']
        

        这将不起作用(属性名称与列定义不同):

        <ng-container matColumnDef="version2">
            <th mat-header-cell *matHeaderCellDef mat-sort-header> Version </th>
            <td mat-cell *matCellDef="let element"> {{element.version}} </td>
        </ng-container>
        
        displayedColumns: string[] = ['version2']
        

        仅供参考,这也不起作用(属性的长度):

        <ng-container matColumnDef="length">
            <th mat-header-cell *matHeaderCellDef mat-sort-header> Version </th>
            <td mat-cell *matCellDef="let element"> {{element.ids.length}} </td>
        </ng-container>
        
        displayedColumns: string[] = ['length']
        

        这也不是:

        <ng-container matColumnDef="ids.length">
            <th mat-header-cell *matHeaderCellDef mat-sort-header> Version </th>
            <td mat-cell *matCellDef="let element"> {{element.ids.length}} </td>
        </ng-container>
        
        displayedColumns: string[] = ['ids.length']
        

        【讨论】:

        • 在第三个选项{{element.ids.length}}的情况下,如果数据已经这样建模,有没有解决办法?
        • @PacoZevallos 我认为解决它的唯一方法是在主对象上设置属性,例如 element.ids_length = element.ids.length
        【解决方案15】:

        对我来说,用 mat-table 标签的 [hidden] 属性替换 *ngIf 是有效的。 如何将此作为错误发布到 Angular Material 社区?

        【讨论】:

          【解决方案16】:

          我找到了这个问题的多个答案,但单独实施它们并没有给我任何结果。所以我尝试合并答案,它奏效了。

          首先,我在 NgAfterViewInit 接口中添加了 ViewChild 排序。 (它最初是在一个通过 NgOnInit 调用的函数中

           ngAfterViewInit(){
              this.tableData.sort = this.sort;
            }
          

          第二步,我将容器内的 *ngIf 更改为 [隐藏]。我确实收到一条错误消息,指出该值未加载。不过到现在都不是大问题。

          之前

          <div class="mat-elevation-z0 container-fluid" *ngIf={some boolean resultant condition}>
          

          之后

          <div class="mat-elevation-z0 container-fluid" [hidden] = {negation of your boolean expression}>
          

          psst.. 您还可以考虑在加载表格时添加加载微调器 mat-footer 到上述 bs 之上。

              <ng-container matColumnDef="loading">
                              <mat-footer-cell *matFooterCellDef colspan=6>
                                  <div class="uploader-status">
                                      <mat-spinner strokeWidth="25" [diameter]="100" title="Server Starting" ></mat-spinner>
                                  </div>
                              </mat-footer-cell>
          </ng-container>
          
          
          <mat-footer-row *matFooterRowDef="['loading']" [ngStyle]="{'display': (this.candidateService.candidateRecords!=null) ? 'none':'block'}"></mat-footer-row>
          

          【讨论】:

            【解决方案17】:

            下面的代码非常适合我,

            @ViewChild(MatSort) set matSort(sort: MatSort) {
            if (!this.dataSource.sort) {this.dataSource.sort = sort;}}
            

            【讨论】:

            • 这对我也有用。经过两天的调试,测试和更改不同的东西,仍然不知道为什么,但是这个解决方案有效。谢谢!
            【解决方案18】:

            在这方面花了几个星期的时间。我找到了你以下

            1. 您需要在 app.module.ts 中导入 MatSortModule。
             imports: [
                ...
                MatSortModule
            ],
            
            <ng-container matColumnDef="ledgerTransactionCreditSum">
                    <th mat-header-cell *matHeaderCellDef mat-sort-header> Ledger Transaction Credit </th>
                    <td mat-cell *matCellDef="let element"> {{element.ledgerTransactionCreditSum}} </td>
                </ng-container>
             matColumnDef and element.ledgerTransactionCreditSum variable and matcolumn def shoulde be same
            
            1. 在 ngViewInit 中定义排序和分页器
            ngAfterViewInit(): void {
                this.dataSource.sort = this.sort;
                this.dataSource.paginator = this.paginator;
                this.dataSource.paginator?._changePageSize(400)
              }
            

            【讨论】:

              【解决方案19】:

              如果您的表在 *ngIf 内,并且您认为它与未对表进行排序有关,那么指定您自己的 sortingDataAccessor 函数可能会像对我一样解决问题。我的桌子在几个 *ngIfs 中,从这些 *ngIfs 中取出是没有意义的:

              `ngAfterViewInit(): void {
                      this.matchesDataSource.sort = this.sort;
                      this.matchesDataSource.sortingDataAccessor = previewMatchSortingFn;
                  }`
              
              `export function previewMatchSortingFn(item: Match, header: string): string | number {
                  switch (header) {
                      case 'home':
                          return item.homeTeam.name;
                      case 'away':
                          return item.awayTeam.name;
                      case 'date':
                          if (item.dateTime) {
                              // this will return the number representation of the date
                              return item.dateTime.valueOf();
                          }
                          return;
                      default:
                          break;
                  }
              }`
              

              【讨论】:

                【解决方案20】:

                如果您在此处阅读了所有答案但没有任何帮助,那么您可能遇到了与我相同的问题。

                问题是我的MatTableDataSource 对象

                dataSource = new MatTableDataSource<StbElement>(ELEMENT_DATA);
                

                在没有this的html文件中使用。

                变化:

                <table mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">
                

                收件人:

                <table mat-table [dataSource]="this.dataSource" matSort class="mat-elevation-z8">
                

                解决了问题。

                【讨论】:

                • 不可能。与此无关,除非材料表包含错误。
                【解决方案21】:

                除了之前的所有答案之外,有时在数据检索时表格是不可见的。例如,我必须在模态/对话框中显示一个带有 MatSort 和 MatPaginator 的表格。因此,我必须通过它们各自的输出发射器函数传递元素,如下所示:

                <... matSort #sort="matSort" (matSortChange)="sortData(sort)">
                <... #paginator (page)="changePaginator(paginator)">
                

                在打字稿中:

                  @ViewChild(MatSort, { static: false }) set sort(s: MatSort) {
                      this.dataSource.sort = s;
                  }
                  @ViewChild(MatPaginator, { static: false }) set paginator(p: MatPaginator) {
                      this.dataSource.paginator = p;
                  }
                
                  sortData(sort: MatSort) {
                      this.sort = sort;
                  }
                  changePaginator(paginator: MatPaginator) {
                      this.paginator = paginator;
                  }
                

                确保在其输入指令中设置分页器的默认值,因为上面的代码将在分页后设置元素,即:[pageSize]="5" [length]="dataSource?.data?.length"。请将此作为所有先前解决方案的最后手段。

                【讨论】:

                  【解决方案22】:

                  mat-sort & mat-paginator 不起作用的主要原因是

                  1. 模块 MatSortModule 和 MatPaginatorModule 未导入
                  2. 表处于 *ngIf 条件下
                  3. matColumnDef 应与 matCellDef 和 displayColumns 相同 数组。

                  【讨论】:

                    【解决方案23】:

                    实际上 matColumnDef 名称(即列名)和您的 Class/Interface 属性名称应该相等才能使其工作。

                    有时我们不能更改我们的类/接口属性名称,在这种情况下,我们可以实现自定义排序如下。

                    let say your columns  as  ['id', 'name'] and 
                    your class/interface  as  ['userId', 'name']
                    

                    如果我们对 'id' 列执行排序,它将不起作用。 尝试自定义排序

                    this.dataSource.sortingDataAccessor = (item,property)=>{
                    
                     // where item is your class/interface data
                     // where property is your column name
                    
                           switch(property){
                               case 'id' : return item.userId
                               default: return item[property];
                            }
                    }
                    

                    【讨论】:

                      【解决方案24】:
                      My solution for this problem is as below - 
                      
                      
                      1. These two lines will go in the same order.
                      
                          this.dataSource = new MatTableDataSource(myRowDataArray);// this dataSource is used in table tag.
                          this.dataSource.sort = this.sort;
                      
                      
                      2. Pass MatTableDataSource object in [dataSource] 
                          <table mat-table [dataSource]="dataSource">
                          // rest of the table definition here
                          </table>
                      
                      3. By default, the MatTableDataSource sorts with the assumption that the sorted column's name matches the data property name that the column displays.
                      
                      Example - 
                          <ng-container matColumnDef="date" >
                                <th class="headers" mat-header-cell  *matHeaderCellDef mat-sort-header>Date</th>
                                <td class="data" mat-cell *matCellDef="let row">{{row.date|date}}</td>
                          </ng-container>
                      
                      4. If the table is inside *ngIf,then replace it with [hidden] or some other filter.
                      

                      我错过了第二点。

                      Cheers!
                      

                      【讨论】:

                        【解决方案25】:

                        此问题主要发生在sortdataSource 之前初始化时。在找到here 的演示中,dataSource 被静态初始化,因此没有发生任何问题。但是,当您必须异步获取数据时,您需要等待 API 调用的响应到达并分配给 dataSource,然后再初始化 sort 实例变量。

                        【讨论】:

                          【解决方案26】:

                          我不知道原因;但是将this.dataSource.sort = this.sort; 赋值给ngAfterViewInit() 方法不起作用。即使我确认此功能在页面加载后仍然无法正常工作。 我的解决方案是将排序分配放在ngOnInit() 方法中。

                           ngOnInit(): void {
                             this.service.getAllAudits().subscribe(result => { 
                              this.dataSource  = new MatTableDataSource(result); 
                              this.dataSource.sort = this.sort; 
                            });
                          

                          }

                          【讨论】:

                            【解决方案27】:

                            变化

                            @ViewChild('matsort') sort: MatSort;
                            

                            @ViewChild(matSort) sort: MatSort
                            

                            为我做的一定是一样的

                            <table mat-table [dataSource]="dataSource" class="mat-elevation-z8" matSort matSortActive="name" matSortDirection="asc">
                            

                            【讨论】:

                              【解决方案28】:

                              查看控制台中是否有任何 javascript 错误。在您的排序初始化之前,可能是其他一些事情失败了。

                              【讨论】:

                                猜你喜欢
                                • 1970-01-01
                                • 2019-07-19
                                • 1970-01-01
                                • 1970-01-01
                                • 2017-03-10
                                • 2012-05-15
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                相关资源
                                最近更新 更多