开发者问题收集

Angular Material 排序,无法设置未定义的属性‘sort’

2019-08-08
17606

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

google 搜索,课程

因此,这是实现排序的文件的样子,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

2个回答

您必须将 this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>();

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

并且在 HTML 中,您必须传递 [dataSource]="datasource" 而不是 [dataSource]="source"

编辑:

您能否像下面这样更改 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
2019-08-08

在您的 html 文件中添加以下代码<table mat-table [dataSource]="listData" matSort (matSortChange)="sortData($event)" >

在 ng 容器中添加以下代码 <th mat-h​​eader-cell *matHeaderCellDef mat-sort-header >Display

在您的 .ts(typescript 代码)中添加以下函数: sortData(sort: Sort) { this.listData.sort = this.sort;

这应该可以解决您的排序问题。

Devesh G
2021-05-17