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

问题描述 投票:0回答:3

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

谷歌搜索,课程

这就是实现排序的文件的样子 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
javascript angular sorting angular-material
3个回答
4
投票

你必须改变

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;



  }


1
投票

在您的 html 文件中添加以下代码

在ng容器中添加以下代码

显示

在您的 .ts(打字稿代码)中添加以下函数: sortData(排序:排序) { this.listData.sort = this.sort; }

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

我也想遇到同样的问题,请问如何解决? 出现箭头但不分类。

// ...
// ...

export class PointComponent implements OnInit {
  displayedColumns: string[] = [ 
    "grupo","unidade","area","setor",
    "equipamento","conjunto",
    "subconjunto","ponto","cila","tag","acoes"
  ];
  dataSource!: MatTableDataSource<Data>; // Altere o tipo de dataSource para MatTableDataSource
  @ViewChild(MatSort, { static: true }) sort!: MatSort; // Adicione a diretiva ViewChild para MatSort
  @ViewChild(MatPaginator) paginator!: MatPaginator;
  data: any[] = [];
  PlantaPonto_Create: boolean = false;
  PlantaPonto_Read: boolean = false; 
  PlantaPonto_Update: boolean = false;
  Tarefacit_Read: boolean = false;
  PlantaPonto_Delete: boolean = false;

  user = { name: "", // Inicialize com uma string vazia
  };

  pageSizeOptions: number[] = [5, 10, 25, 100];
  pageSize = this.pageSizeOptions[0];
  pageIndex = 0;  
  qtde_pages = paginator_qtde_pages;
  
  filterForm!: FormGroup;
  constructor(
    private fb: FormBuilder, 
    private router: Router, 
    private modalService: ModalService,
    private service: PointService,
    private toastService: ToastService,
    private permissionService: PermissionService
    ) {
    this.createForm();
  }
  createForm(): void {
    this.filterForm = this.fb.group({
      name: [""],
    });
  }

  sortData(sort: Sort) { 
    this.dataSource.sort = this.sort; 
  }

  ngOnInit() {
    this.PlantaPonto_Create = this.permissionService.hasPermission("PlantaPonto_Create");
    this.PlantaPonto_Read = this.permissionService.hasPermission("PlantaPonto_Read");
    this.PlantaPonto_Update = this.permissionService.hasPermission("PlantaPonto_Update");
    this.PlantaPonto_Delete = this.permissionService.hasPermission("PlantaPonto_Delete");
    this.Tarefacit_Read = this.permissionService.hasPermission("Tarefacit_Read");
    const userDataString = localStorage.getItem('user');
    if (userDataString !== null) {
      const userData = JSON.parse(userDataString);

      // Verificar se os dados do usuário e a unidade existem
      if (userData && userData.unidade_padrao && userData.unidade_padrao.id) {
        const unidadeId = userData.unidade_padrao.id;

        // Fazer a solicitação à API
        this.service.list(unidadeId).subscribe(
          (data: any) => {
            this.data = data;
            // Inicialize o MatTableDataSource com os dados
            this.dataSource = new MatTableDataSource<Data>(this.data);
            this.dataSource.sort = this.sort; // Atribua o sort à fonte de dados
            this.dataSource.paginator = this.paginator
            this.updateDataSource(); 
          },
          (error) => {
            // Lidar com erros, se necessário
            console.error('Erro ao buscar os dados', error);
          }
        );
      } else {
        // Caso a estrutura dos dados não seja a esperada
        console.error('Estrutura de dados inválida na Local Storage.');
      }
    } else {
      // Caso os dados do usuário não estejam na Local Storage
      console.error('Dados do usuário não encontrados na Local Storage.');
    }
  }
  
 // ...
 // ...
 // ...
<basic-page title="Ponto">
    <ng-container  *ngIf="PlantaPonto_Create" contentTitle>
      <button routerLink="/point/register" matTooltip="Adicionar" id="PlantaPonto_Create" mat-raised-button color="primary">Adicionar</button>
    </ng-container>
  
    <ng-container advancedFilter>
      <div [formGroup]="filterForm">
        <mat-form-field>
          <mat-label>Name</mat-label>
          <input matInput formControlName="name" />
        </mat-form-field>
      </div>
    </ng-container>
  
    <table  *ngIf="PlantaPonto_Read" mat-table [dataSource]="dataSource" class="mat-elevation-z8" matSort (matSortChange)="sortData($event)">


      <ng-container matColumnDef="grupo">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Grupo</th>
        <td mat-cell *matCellDef="let element">{{ element.grupo }}</td>
      </ng-container>
  
      <ng-container matColumnDef="unidade">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Unidade</th>
        <td mat-cell *matCellDef="let element">{{ element.unidade }}</td>
      </ng-container>
  
      <ng-container matColumnDef="area">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Area</th>
        <td mat-cell *matCellDef="let element">{{ element.area }}</td>
      </ng-container>

<!-- ... -->
<!-- ... -->
<!-- ... -->


0
投票

我也想遇到同样的问题,请问如何解决? 出现箭头但不分类。

// ...
// ...

export class PointComponent implements OnInit {
  displayedColumns: string[] = [ 
    "grupo","unidade","area","setor",
    "equipamento","conjunto",
    "subconjunto","ponto","cila","tag","acoes"
  ];
  dataSource!: MatTableDataSource<Data>; // Altere o tipo de dataSource para MatTableDataSource
  @ViewChild(MatSort, { static: true }) sort!: MatSort; // Adicione a diretiva ViewChild para MatSort
  @ViewChild(MatPaginator) paginator!: MatPaginator;
  data: any[] = [];
  PlantaPonto_Create: boolean = false;
  PlantaPonto_Read: boolean = false; 
  PlantaPonto_Update: boolean = false;
  Tarefacit_Read: boolean = false;
  PlantaPonto_Delete: boolean = false;

  user = { name: "", // Inicialize com uma string vazia
  };

  pageSizeOptions: number[] = [5, 10, 25, 100];
  pageSize = this.pageSizeOptions[0];
  pageIndex = 0;  
  qtde_pages = paginator_qtde_pages;
  
  filterForm!: FormGroup;
  constructor(
    private fb: FormBuilder, 
    private router: Router, 
    private modalService: ModalService,
    private service: PointService,
    private toastService: ToastService,
    private permissionService: PermissionService
    ) {
    this.createForm();
  }
  createForm(): void {
    this.filterForm = this.fb.group({
      name: [""],
    });
  }

  sortData(sort: Sort) { 
    this.dataSource.sort = this.sort; 
  }

  ngOnInit() {
    this.PlantaPonto_Create = this.permissionService.hasPermission("PlantaPonto_Create");
    this.PlantaPonto_Read = this.permissionService.hasPermission("PlantaPonto_Read");
    this.PlantaPonto_Update = this.permissionService.hasPermission("PlantaPonto_Update");
    this.PlantaPonto_Delete = this.permissionService.hasPermission("PlantaPonto_Delete");
    this.Tarefacit_Read = this.permissionService.hasPermission("Tarefacit_Read");
    const userDataString = localStorage.getItem('user');
    if (userDataString !== null) {
      const userData = JSON.parse(userDataString);

      // Verificar se os dados do usuário e a unidade existem
      if (userData && userData.unidade_padrao && userData.unidade_padrao.id) {
        const unidadeId = userData.unidade_padrao.id;

        // Fazer a solicitação à API
        this.service.list(unidadeId).subscribe(
          (data: any) => {
            this.data = data;
            // Inicialize o MatTableDataSource com os dados
            this.dataSource = new MatTableDataSource<Data>(this.data);
            this.dataSource.sort = this.sort; // Atribua o sort à fonte de dados
            this.dataSource.paginator = this.paginator
            this.updateDataSource(); 
          },
          (error) => {
            // Lidar com erros, se necessário
            console.error('Erro ao buscar os dados', error);
          }
        );
      } else {
        // Caso a estrutura dos dados não seja a esperada
        console.error('Estrutura de dados inválida na Local Storage.');
      }
    } else {
      // Caso os dados do usuário não estejam na Local Storage
      console.error('Dados do usuário não encontrados na Local Storage.');
    }
  }
  
 // ...
 // ...
 // ...
<basic-page title="Ponto">
    <ng-container  *ngIf="PlantaPonto_Create" contentTitle>
      <button routerLink="/point/register" matTooltip="Adicionar" id="PlantaPonto_Create" mat-raised-button color="primary">Adicionar</button>
    </ng-container>
  
    <ng-container advancedFilter>
      <div [formGroup]="filterForm">
        <mat-form-field>
          <mat-label>Name</mat-label>
          <input matInput formControlName="name" />
        </mat-form-field>
      </div>
    </ng-container>
  
    <table  *ngIf="PlantaPonto_Read" mat-table [dataSource]="dataSource" class="mat-elevation-z8" matSort (matSortChange)="sortData($event)">


      <ng-container matColumnDef="grupo">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Grupo</th>
        <td mat-cell *matCellDef="let element">{{ element.grupo }}</td>
      </ng-container>
  
      <ng-container matColumnDef="unidade">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Unidade</th>
        <td mat-cell *matCellDef="let element">{{ element.unidade }}</td>
      </ng-container>
  
      <ng-container matColumnDef="area">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Area</th>
        <td mat-cell *matCellDef="let element">{{ element.area }}</td>
      </ng-container>

<!-- ... -->
<!-- ... -->
<!-- ... -->

© www.soinside.com 2019 - 2024. All rights reserved.