Angular Material排序,无法设置未定义属性“sort”。

4

我有一个使用Angular Material的Angular 8应用程序。 我想在Angular 8应用程序中使用Angular Material对列进行排序。

搜索了谷歌和课程资料。

以下是实现排序的ts文件:

import { ActivatedRoute } from '@angular/router';
import { Component, OnInit, ViewChild, Inject, Input } from '@angular/core';
import { QRCodeDefinitionInfoApi, EcheqSubmissionInfoApi, QRCodeMedicalService } from 'src/app/generated';
import { MatPaginator, MatSort } from '@angular/material';
import { MAT_DIALOG_DATA, MatTableDataSource } from '@angular/material';
import { PublishState } from 'src/app/qrcode-definition/list/list-item';
import { I18n } from '@ngx-translate/i18n-polyfill';

class SortedSubmissions {
  [key: string]: {
    submissions: EcheqSubmissionInfoApi[];
  };
}


@Component({
  selector: 'app-echeq-qrcode',
  templateUrl: './echeq-qrcode.component.html',
  styleUrls: ['./echeq-qrcode.component.scss']
})
export class EcheqQrcodeComponent implements OnInit {

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

  readonly ScanFequencyType = QRCodeDefinitionInfoApi.ScanFrequencyTypeEnum;
  readonly PublishState = QRCodeDefinitionInfoApi.PublishStateEnum;
  readonly ActionType = QRCodeDefinitionInfoApi.ActionTypeEnum;
  source: QRCodeDefinitionInfoApi[];
  datasource: MatTableDataSource<QRCodeDefinitionInfoApi>;

  patientId: string;
  submissions: EcheqSubmissionInfoApi[];


  @Inject(MAT_DIALOG_DATA) public data: any;
  @Input() item;
  sortedSubmissions: SortedSubmissions;

  public readonly displayedColumns = [

    'title',
    'lastScannedOn',
    'totalScanned',
    'publishState',
  ];

  constructor(private i18n: I18n, route: ActivatedRoute,  private qrCodeDefintion: QRCodeMedicalService ) {

    this.patientId = route.snapshot.paramMap.get('patientId');
    const data = route.snapshot.data;
    this.source = data.definition;

    }

  ngOnInit() {

    this.qrCodeDefintion.getQRCodeList(1, this.patientId).subscribe((subs) => {
    (this.source = subs);
    });

    if (this.data && this.data.definition) {
      this.source = this.data.definition;
    }
    // this.datasource.paginator = this.paginator;
    this.datasource.sort = this.sort;
  }

  translatePublished(publishState: PublishState): string {
    switch (publishState) {
      case PublishState.DRAFT:
        return this.i18n('Not published');
      case PublishState.PUBLISHED:
        return this.i18n('Published');
    }
    switch ( String(publishState) ) {
      case 'Draft':
          return this.i18n('Not published');
      case 'Published':
        return this.i18n('Published');
      default:
        return this.i18n( 'Not Published' );
    }
  }
}

以下是网页的HTML代码:

<div class="header">
    <h1 class="heading page-heading patient-list-heading">Scanned QR Codes </h1>
  <div class="qrcode-menu">
  </div>
</div>

  <div class="mat-elevation-z8">
    <table
      mat-table
      class="full-width-table"
      [dataSource]="source"
      matSort
      aria-label="Elements"
    >
    <ng-container matColumnDef="title">
      <th mat-header-cell *matHeaderCellDef mat-sort-header i18n>Name</th>
      <td mat-cell *matCellDef="let row">{{ row.title }}</td>
    </ng-container>


    <ng-container matColumnDef="lastScannedOn">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>lastScannedOn</th>
      <td mat-cell *matCellDef="let row">{{ row.lastScannedOn | date: 'dd MMM yy' }}</td>
    </ng-container>

    <ng-container matColumnDef="totalScanned">
      <th mat-header-cell *matHeaderCellDef mat-sort-header i18n>totalScanned</th>
      <td mat-cell *matCellDef="let row">{{ row.totalScanned }}</td>
    </ng-container>

    <ng-container matColumnDef="publishState">
      <th mat-header-cell *matHeaderCellDef mat-sort-header="wasPublished" i18n>publishState</th>
      <td mat-cell *matCellDef="let row">{{ translatePublished(row.publishState) }}</td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
  </table>
  <mat-paginator [pageSizeOptions]="[25, 50, 100, 250]"></mat-paginator>
  </div>




但现在我遇到了这个错误:

ERROR TypeError: Cannot set property 'sort' of undefined
    at EcheqQrcodeComponent.push../src/app/components/echeq-qrcode/echeq-qrcode.component.ts.EcheqQrcodeComponent.ngOnInit (echeq-qrcode.component.ts:66)
    at checkAndUpdateDirectiveInline (core.js:18620)
    at checkAndUpdateNodeInline (core.js:19884)
    at checkAndUpdateNode (core.js:19846)
    at debugCheckAndUpdateNode (core.js:20480)
    at debugCheckDirectivesFn (core.js:20440)
    at Object.eval [as updateDirectives] (EcheqQrcodeComponent_Host.ngfactory.js?

那样排序将适用于每一列。

谢谢你

如果我这样做:

 ngOnInit() {

    this.qrCodeDefintion.getQRCodeList(1, this.patientId).subscribe((subs) => {
    (this.source = subs);
    });

    if (this.data && this.data.definition) {
      this.source = this.data.definition;
    }
    // this.datasource.paginator = this.paginator;
    this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>();
    this.datasource.sort = this.sort;
  }

我没有收到错误提示,但是排序完全不起作用。

我的ngOnit现在看起来像这样:

ngOnInit() {

    this.qrCodeDefintion.getQRCodeList(1, this.patientId).subscribe((subs) => {
    (this.source = subs);


    });

    if (this.data && this.data.definition) {
      this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>(this.source);
      this.datasource.sort = this.sort;
      this.datasource.paginator = this.paginator;
      this.source = this.data.definition;
    }
    // this.datasource.paginator = this.paginator;



  }

但是如果我这样做:

 <div class="mat-elevation-z8">
    <table
      mat-table
      class="full-width-table"
      [dataSource]="datasource"
      matSort
      aria-label="Elements"
    >

那么数据就不再可见了。

谢谢。但是如果我这样做,我会得到这个错误:

是的,谢谢。但现在我收到了这个错误:this.source =

this.data.definition;

core.js:12584 ERROR TypeError: Cannot read property 'definition' of undefined
    at SafeSubscriber._next (echeq-qrcode.component.ts:61)
    at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:196)

这是目前我的做法:

ngOnInit() {

    this.qrCodeDefintion.getQRCodeList(1, this.patientId).subscribe((subs) => {
      (this.source = subs);
        this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>(this.source);
        this.datasource.sort = this.sort;
        this.datasource.paginator = this.paginator;
        this.source = this.data.definition;

      });
  }

以下是 HTML 文件的内容:

<div class="header">
    <h1 class="heading page-heading patient-list-heading">Scanned QR Codes </h1>
  <div class="qrcode-menu">
  </div>
</div>

  <div class="mat-elevation-z8">
    <table
      mat-table
      class="full-width-table"
      [dataSource]="source"
      matSort
      aria-label="Elements"
    >
    <ng-container matColumnDef="title">
      <th mat-header-cell *matHeaderCellDef mat-sort-header i18n>Name</th>
      <td mat-cell *matCellDef="let row">{{ row.title }}</td>
    </ng-container>


    <ng-container matColumnDef="lastScannedOn">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>lastScannedOn</th>
      <td mat-cell *matCellDef="let row">{{ row.lastScannedOn | date: 'dd MMM yy' }}</td>
    </ng-container>

    <ng-container matColumnDef="totalScanned">
      <th mat-header-cell *matHeaderCellDef mat-sort-header i18n>totalScanned</th>
      <td mat-cell *matCellDef="let row">{{ row.totalScanned }}</td>
    </ng-container>

    <ng-container matColumnDef="publishState">
      <th mat-header-cell *matHeaderCellDef mat-sort-header="wasPublished" i18n>publishState</th>
      <td mat-cell *matCellDef="let row">{{ translatePublished(row.publishState) }}</td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
  </table>
  <mat-paginator [pageSizeOptions]="[25, 50, 100, 250]"></mat-paginator>
  </div>

我也尝试过这个:

ngAfterViewInit () {

    this.qrCodeDefintion.getQRCodeList(1, this.patientId).subscribe((subs) => {
      (this.source = subs);
    this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>(this.source);
    setTimeout(() => {
      this.datasource.sort = this.sort;
      this.datasource.paginator = this.paginator;

    });
  });

没有出现任何错误。但排序不起作用。

如果我在ngAfterViewInit(){}中执行console.log(this.datasource.sort),则会看到以下内容:

然后我看到这个:

MatSort {_disabled: false, _isInitialized: true, _pendingSubscribers: null, initialized: Observable, sortables: Map(4), …}
direction: (...)
disableClear: (...)
disabled: (...)
initialized: Observable {_isScalar: false, _subscribe: ƒ}
sortChange: EventEmitter
closed: false
hasError: false
isStopped: false
observers: (5) [Subscriber, Subscriber, Subscriber, Subscriber, Subscriber]
thrownError: null
__isAsync: false
_isScalar: false
__proto__: Subject
sortables: Map(4)
size: (...)
__proto__: Map
[[Entries]]: Array(4)
0: {"title" => MatSortHeader}
key: "title"
value: MatSortHeader {_disabled: false, _intl: MatSortHeaderIntl, _sort: MatSort, _columnDef: MatColumnDef, _showIndicatorHint: false, …}
1: {"lastScannedOn" => MatSortHeader}
2: {"totalScanned" => MatSortHeader}
3: {"wasPublished" => MatSortHeader}
length: 4
start: "asc"
_direction: ""
_disabled: false
_isInitialized: true
_pendingSubscribers: null
_stateChanges: Subject {_isScalar: false, observers: Array(4), closed: false, isStopped: false, hasError: false, …}
__proto__: class_1

看起来这是正确的。不是吗?

如果我这样做:

  sortData(sort: Sort)     {
       this.datasource.sort = this.sort;
       console.log(this.datasource.sort);
      }

我看到这个:

MatSort {_disabled: false, _isInitialized: true, _pendingSubscribers: null, initialized: Observable, sortables: Map(4), }
active: "totalScanned"
direction: (...)
disableClear: (...)
disabled: (...)
initialized: Observable {_isScalar: false, _subscribe: ƒ}
sortChange: EventEmitter {_isScalar: false, observers: Array(6), closed: false, isStopped: false, hasError: false, }
sortables: Map(4) {"title" => MatSortHeader, "lastScannedOn" => MatSortHeader, "totalScanned" => MatSortHeader, "wasPublished" => MatSortHeader}
start: "asc"
_direction: "desc"
_disabled: false
_isInitialized: true
_pendingSubscribers: null
_stateChanges: Subject {_isScalar: false, observers: Array(4), closed: false, isStopped: false, hasError: false, }
__proto__: class_1

您从未初始化 datasource: MatTableDataSource<QRCodeDefinitionInfoApi>;,因此它是 undefined - Fullstack Guy
这意味着您正在对未定义的字段应用排序。 - Chaitanya
我更新了帖子。 - mightycode Newton
你需要在 new MatTableDataSource<QRCodeDefinitionInfoApi>(here); 的构造函数中传递应该出现在 mat 表格中的数据。 - Fullstack Guy
请问您能否在更改后发布您的ngOnInit方法代码? - Kinjal
我编辑了这篇文章。 - mightycode Newton
2个回答

4

你需要将 this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>();

修改为 this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>(this.source);

在HTML中,你需要将 [dataSource]="source" 修改为[dataSource]="datasource"

编辑:

请修改您的ngOnInit方法如下所示:


ngOnInit() {

    this.qrCodeDefintion.getQRCodeList(1, this.patientId).subscribe((subs) => {
    (this.source = subs);
      this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>(this.source);
      this.datasource.sort = this.sort;
      this.datasource.paginator = this.paginator;
      this.source = this.data.definition;

    });
    // this.datasource.paginator = this.paginator;



  }


我已经在给定的解决方案中添加了编辑功能,您可以尝试一下。 - Kinjal
谢谢。我已经做了那个。但是没有任何反应。我看到箭头,但排序没有任何作用。也没有错误。 - mightycode Newton
你能否在Stackblitz上创建演示来检查这个问题? - Kinjal
谢谢!但是你具体改了什么? - mightycode Newton
这解决了问题,但我在悬停时没有得到那些标题上的图标。缺少什么?另外,标题上的HTML是纯文本,只有th。 - Santosh
显示剩余5条评论

1
在您的HTML文件中添加以下代码,<table mat-table [dataSource]="listData" matSort (matSortChange)="sortData($event)" >。
在ng容器中添加以下代码,<th mat-header-cell *matHeaderCellDef mat-sort-header >Display。
在您的.ts(typescript代码)中添加以下函数:sortData(sort: Sort) { this.listData.sort = this.sort; }。
这应该解决您的排序问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接