首页 > 解决方案 > Angular6 Problems with sorting | paginating material-table

问题描述

I try to display a complex json structure (received from a REST endpoint) to my Angular6 material-data-table application. This works so far, but I also try to include pagination and sorting into my application (no success at all).

I tried all stackoverflow threads, that I found, but no given solution seemed to work. Maybe the problem is caused because I address the REST data wrongly (although I am able to access the data in the consructor), but I couldnt find out the problem. No error message gets displayed. All Imports should be okay.

file: employee-list.ts

import { MatSort } from '@angular/material/sort';
import { MatTableDataSource, MatPaginator } from '@angular/material';
import { Component, OnInit, ViewChild } from '@angular/core';
import { UserService } from '../../services/user.service';
import { Entry } from '../../interfaces/entry';


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

  typesafeEntries: Entry[];
  listData: MatTableDataSource<Entry>;
  displayedColumns: string[] = ['searched', 'german', 'dialectEntry', 'partOfSpeech', 'linguisticUsage', 'synonyms', 'actions'];

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


  constructor(private userService: UserService) {

    this.userService.getCompleteSearchResults("SomeLanguageData1", "SomeLanguageData2", "wordToLookFor")
      .subscribe((resp: Entry[]) => {;

        this.typesafeEntries = resp;
        this.listData = new MatTableDataSource<Entry>(this.typesafeEntries);
        this.listData.sort = this.sort;

      });
  }

  ngOnInit() {  }

}
<div class="mat-elevation-z8">
  <mat-table [dataSource]="listData" matSort>
    <ng-container matColumnDef="searched">
     // some code
    </ng-container>


    <ng-container matColumnDef="german">
    // some code
    </ng-container>

    <!-- neue spalte: -->
    <ng-container matColumnDef="dialectEntry">
      <mat-header-cell *matHeaderCellDef mat-sort-header>       // e.g. this table should become sorted.
        Dialekt B
      </mat-header-cell>
      <mat-cell *matCellDef="let element">{{
        element.dialectB.dialectEntry
      }}</mat-cell>
    </ng-container>






    //from here on the code should no longer be important for the solution
     //...

    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
    <!-- loading screen -->
    <mat-footer-row
      *matFooterRowDef="['loading']"
      [ngClass]="{ hide: listData != null }"
    ></mat-footer-row>
    <mat-footer-row
      *matFooterRowDef="['noData']"
      [ngClass]="{ hide: !(listData != null && listData.data.length == 0) }"
    ></mat-footer-row>
    <!-- <mat-footer-row *matFooterRowDef="['noData']" [ngClass]="{'hide':!(true == false)}"></mat-footer-row> -->
  </mat-table>

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

consumed JSON:

[
    {
        "dialectA": {
            "dialectId": "5d1220343269a28de043eda9",
            "dialectEntry": "House",
            "dialectEntryLowerCase": "house",
            "partOfSpeech": {
                "partOfSpeechs": [
                    "INTERJECTION",
                    "ARTICLE"
                ]
            },
            "linguisticUsage": {
                "linguisticUsages": [
                    "ACAD",
                    "SCIENCE"
                ]
            },
            "refToGermanId": "5d1220053269a28de043eda3",
            "synonymIds": []
        },
        "german": {
            "germanId": "5d1220053269a28de043eda3",
            "germanEntry": "Haus",
            "germanEntryLowerCase": "haus",
            "reverseTranslations": [
                {
                    "reverseGerman2DialectLanguage": "dornbirnerisch",
                    "reverseGerman2DialectIdList": [
                        "5d1220343269a28de043eda9"
                    ]
                },
                {
                    "reverseGerman2DialectLanguage": "tirolerisch",
                    "reverseGerman2DialectIdList": [
                        "5d1221893269a28de043edaf"
                    ]
                }
            ]
        },
        "dialectB": {
            "dialectId": "5d1221893269a28de043edaf",
            "dialectEntry": "person",
            "dialectEntryLowerCase": "person",
            "partOfSpeech": {
                "partOfSpeechs": [
                    "INTERJECTION",
                    "ARTICLE"
                ]
            },
            "linguisticUsage": {
                "linguisticUsages": [
                    "ACAD",
                    "SCIENCE"
                ]
            },
            "refToGermanId": "5d1220053269a28de043eda3",
            "synonymIds": []
        }
    },
// end of first entry
{...}, {...} ]

Expected result: when clicking on sort, the content of this column should be sorted. the same with pagination.

here a screenshot: screenshot from project

标签: angulartypescript

解决方案


对该列进行排序不起作用,因为 Angular Material 试图根据列名(在本例中为dialectEntry)对表数据进行排序,但该列的实际数据嵌套在另一个属性element.dialectB.dialectEntry中。因此 Angular Material 正在寻找 下的数据element.dialectEntry,但由于它不存在,因此排序不起作用。

在这种情况下,您需要自己编写sortingDataAccessor并告诉 Angular Material 在哪里查找数据。请参阅此处的文档以获取sortingDataAccessor.

对于您的情况,这将如下所示:

this.listData.sortingDataAccessor = (item, property) => {
  if (property === 'dialectEntry') {
    return item.dialectB.dialectEntry;
  } else {
    return item[property];
  }
};

推荐阅读