【问题标题】:Angular 5 Material Data Table sorting not workingAngular 5 材料数据表排序不起作用
【发布时间】:2018-12-07 08:58:57
【问题描述】:

所以我在我的 Angular 5 应用程序中有一个工作的 Angular 材料数据表,但是当我尝试添加排序功能时(基于此处的官方文档:https://material.angular.io/components/table/overview#sorting 和此处的示例:https://stackblitz.com/angular/dnbermjydavk?file=app%2Ftable-overview-example.html)我不能让它工作。它似乎确实添加了排序功能/箭头,我可以单击它,但没有任何反应。

这是我的 HTML:

<div class="container">
  <mat-table #table class="dataTable" *ngIf="showDataForm;else loadingTemplate" [dataSource]="dataSource" matSort>
    <ng-container matColumnDef="id">
      <mat-header-cell *matHeaderCellDef mat-sort-header>ID</mat-header-cell>
      <mat-cell *matCellDef="let item">{{item.id}}</mat-cell>
    </ng-container>
    <ng-container matColumnDef="titel">
      <mat-header-cell *matHeaderCellDef mat-sort-header>Titel</mat-header-cell>
      <mat-cell *matCellDef="let item">{{item.titel}}</mat-cell>
    </ng-container>
    <ng-container matColumnDef="EADDraftingStage">
      <mat-header-cell *matHeaderCellDef mat-sort-header>EADDraftingStage</mat-header-cell>
      <mat-cell *matCellDef="let item">{{item.EADDraftingStage}}</mat-cell>
    </ng-container>

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

  <mat-paginator [pageSize]="10" [pageSizeOptions]="[5, 10, 25]" showFirstLastButtons></mat-paginator>
</div>

<ng-template #loadingTemplate>
  <div>
      <p>Please wait, the data is loading...</p>
      <img src="../../assets/giphy.gif">
  </div>
</ng-template>

<button mat-raised-button class="submitButton" color="accent" (click)="logout()">Logout and remove cookie</button>  

这是我的 TS:

import { Component, OnInit, ChangeDetectorRef, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { CookieService } from 'ngx-cookie-service';
import { LoginService } from '../Services/login.service';
import { TableService } from '../Services/table.service';
import { EADProcess } from '../Classes/EADProcess';
import { MatTableDataSource, MatPaginator, MatSort } from '@angular/material';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { map, tap, catchError } from 'rxjs/operators';

@Component({
  selector: 'app-table',
  templateUrl: './table.component.html',
  styleUrls: ['./table.component.css']
})
export class TableComponent implements OnInit {

  showDataForm = false;

  stringArray: string[] = [];
  eadItems: EADProcess[] = [];

  dataSource: MatTableDataSource<EADProcess>;

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;

  // which columns the data table needs to display
  columnsToDisplay: string[] = ['id', 'titel', 'EADDraftingStage'];

  constructor(private router: Router,
              private cookieService: CookieService,
              private loginService: LoginService,
              private tableService: TableService,
              private chRef: ChangeDetectorRef) {

  }

  ngOnInit() {
    const $this = this;

    this.getAllEadItems();
  }

  public getAllEadItems() {
    const json: any = {(data omitted for this example)};

    const jsonStringified = JSON.stringify(json);

    this.tableService.getAllEadItems(jsonStringified).subscribe(res => {
      this.convertJsonResultToArray(res);
      this.dataSource = new MatTableDataSource(this.eadItems);
      this.dataSource.paginator = this.paginator;
      this.dataSource.sort = this.sort;
      this.showDataForm = true;
    });
  }

  public convertJsonResultToArray(res: any) {
    this.stringArray = JSON.parse(res);
    for (const eadItem of this.stringArray) {
      const ead = new EADProcess();
      ead.id = eadItem['GUID'];
      ead.titel = eadItem['Title'];
      ead.EADDraftingStage = eadItem['EADDraftingStage'];

      this.eadItems.push(ead);
    }
  }

  public logout() {
    this.cookieService.delete('logindata');
    this.loginService.setLoggedIn(false);
    this.router.navigateByUrl('/login');
  }

}

所以要重新迭代,我的数据表可以很好地显示数据,但是现在我想添加排序功能,当我按下我想要排序的标题单元格时,它似乎并没有真正排序。有人看到问题了吗?

【问题讨论】:

  • 你能用你的代码创建 stackblitz 吗?

标签: angular angular-datatables


【解决方案1】:
export class SomeComponent implements OnInit, AfterViewInit {       
      public rows = [];
      public dataSource = new MatTableDataSource<SomeElement>([]);    

  constructor(public dialogRef: MatDialogRef<SomeComponent>, @Inject(MAT_DIALOG_DATA) public data: ReportData) {}    

  @ViewChild(MatSort) sort;

  ngOnInit(): void {
    this.rows.push({...});    
    this.rows.push({...});    
    this.rows.push({...});    
    this.dataSource = new MatTableDataSource(this.rows);    
  }    

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

【讨论】:

    【解决方案2】:

    如果有人仍然有问题并且需要更清洁的方法,他们可以实现ngAfterViewInit 接口并实现它。它是在 Angular 完全初始化组件视图后调用的生命周期钩子。 通过引用提问者的代码,可以通过以下代码更新TS。

    import { Component, OnInit, ChangeDetectorRef, ViewChild, AfterViewInit  } from '@angular/core';
    ...
    ...
    
    export class TableComponent implements OnInit, AfterViewInit {
       ...
       ...
       ngAfterViewInit() {
          this.dataSource.sort = this.sort; // apply sort after view has been initialized.
       }
    
    } 
    

    【讨论】:

      【解决方案3】:

      您遇到的问题是 mat-table 选择器中的 *ngIf。如果你检查 this.sort 你会看到它是未定义的。这有效:

      export class TableComponent implements OnInit { 
      sort;
      @ViewChild(MatSort) set content(content: ElementRef) {
        this.sort = content;
        if (this.sort){
           this.dataSource.sort = this.sort;
      
        }
      }
      

      我不记得这里的答案是什么,所以我用作解决方案的指南。

      【讨论】:

      • 谢谢,这成功了!你能解释一下为什么它必须是这样的吗?我对 Angular 很陌生,并不完全理解这个 ViewChild 的作用。它是否基本上根据对象从我的视图中获取一个元素,但由于我不显示它,它会得到“空”/未定义?那么你的方法是如何防止这种情况发生的呢?它确实“设置内容”吗?当内容显示在视图上时,这是否会等待并触发?
      • 我用stackoverflow.com/questions/39366981/…作为基础,它说一旦*ngIf变为true,就会调用setter。
      • 这太棒了!!!我确实花了几个小时试图弄清楚为什么它不会排序,这解决了它!你是绅士和学者我的朋友@wFitz
      • 在这种特殊情况下使用 [hidden] 而不是 *ngIf。它不会干扰您的排序。
      【解决方案4】:

      这可能是因为您的排序器未正确绑定到您的数组。

      尝试使用超时来延迟绑定:

      this.convertJsonResultToArray(res);
      this.dataSource = new MatTableDataSource(this.eadItems);
      setTimeout(() => {
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;
      
      });
      this.showDataForm = true;
      

      【讨论】:

      • 这是我的问题。我必须在订阅服务期间分配排序。
      猜你喜欢
      • 2018-08-23
      • 2020-01-20
      • 2019-01-28
      • 2018-10-29
      • 2019-09-20
      • 2019-01-03
      • 2021-07-17
      • 1970-01-01
      相关资源
      最近更新 更多