Angular material table 在 sort + @Input() 时不起作用

Angular material table does not work when sort + @Input()

我正在做一个 table 组件。

此组件在没有 sortable 功能的情况下也能完美运行。 当我尝试制作 table sortable 时,如果我在使用基本示例时将对象列表存储在常量中但在我尝试使用时不显示行,则该方法有效@Input()

具有常量的版本 - 有效

import {AfterContentInit, AfterViewInit, Component, Input, OnInit, ViewChild} from '@angular/core';
import {Client, ClientStatus} from '@models/client.model';
import {ClientService} from '@services/client.service';
import {MatSort, Sort} from '@angular/material/sort';
import {MatTableDataSource} from '@angular/material/table';

const ELEMENT_DATA: Client[] = [
 ...
];

@Component({
  selector: 'app-table-entries',
  templateUrl: './table-entries.component.html',
  styleUrls: ['./table-entries.component.scss']
})
export class TableEntriesComponent implements OnInit, AfterViewInit {
  displayedColumns: string[] = ['expectedDate', 'description.id', 'priority' ];
  @ViewChild(MatSort, {static: true}) sort: MatSort;
  sortableEntries = new MatTableDataSource(ELEMENT_DATA);

  constructor( clientService: ClientService ) {}
  ngOnInit(): void {}

  ngAfterViewInit() {
    this.sort.active = 'expectedDate';
    this.sort.direction = 'asc';
    this.sortableEntries.sort = this.sort;
    this.sortableEntries.sortingDataAccessor = ( client, property) => {
      switch ( property ) {
        case 'description.id': return client.description.id;
        default: return client[property];
      }
    };
  }
}

带有@Input 的版本 - 这不起作用

import {AfterContentInit, AfterViewInit, Component, Input, OnInit, ViewChild} from '@angular/core';
import {Client, ClientStatus} from '@models/client.model';
import {ClientService} from '@services/client.service';
import {MatSort, Sort} from '@angular/material/sort';
import {MatTableDataSource} from '@angular/material/table';

@Component({
  selector: 'app-table-entries',
  templateUrl: './table-entries.component.html',
  styleUrls: ['./table-entries.component.scss']
})
export class TableEntriesComponent implements OnInit, AfterViewInit {
  @Input() entries: Client[] = [];
  displayedColumns: string[] = ['expectedDate', 'description.id', 'priority' ];
  @ViewChild(MatSort, {static: true}) sort: MatSort;
  sortableEntries: MatTableDataSource<Client>;

  constructor( clientService: ClientService ) {}
  ngOnInit(): void {
      this.sortableEntries = new MatTableDataSource<Client>( this.entries );
  }

  ngAfterViewInit() {
    this.sort.active = 'expectedDate';
    this.sort.direction = 'asc';
    this.sortableEntries.sort = this.sort;
    this.sortableEntries.sortingDataAccessor = ( client, property) => {
      switch ( property ) {
        case 'description.id': return client.description.id;
        default: return client[property];
      }
    };
  }
}

模板

<table mat-table matSort [dataSource]="sortableEntries">
  <!-- Heure RDV -->
  <ng-container matColumnDef="expectedDate">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> Heure rdv </th>
    <td mat-cell *matCellDef="let element"> {{ element.expectedDate | date: "d/M HH:mm" }} </td>
  </ng-container>

  <!-- Identifiant -->
  <ng-container matColumnDef="description.id">
    <th mat-header-cell *matHeaderCellDef mat-sort-header="description.id"> Identifiant </th>
    <td mat-cell *matCellDef="let element"> {{ element.description.id}} </td>
  </ng-container>

  <!-- Nature -->
  <ng-container matColumnDef="priority">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> Nature </th>
    <td mat-cell *matCellDef="let element" > {{ element.priority | getStringPriority }} </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
  <tr mat-row *matRowDef="let row; let even = even; columns: displayedColumns;" [ngClass]="{ 'table-even-row': even}"></tr>
</table>
<section *ngIf="entries && entries.length === 0" class="no-client-wrapper"><p>Il n'y a pas d'entrée actuellement</p></section>

我可以想象问题出在加载对象列表的那一刻,但我不知道如何解决这个问题。 有人有想法吗?

我找到了 solution here.

首先,将@Input() entries: Client[] = [];改为

@Input() set entries( data: Client[] ) {
  this.setTableDataSource(data);
}

然后,使用ngAfterViewInit中的内容制作函数

setTableDataSource(data: any) {
    this.sortableEntries = new MatTableDataSource<any>(data);
    this.sortableEntries.sort = this.sort;
    this.sort.active = 'expectedDate';
    this.sort.direction = 'asc';
    this.sortableEntries.sortingDataAccessor = ( client, property) => {
      switch ( property ) {
        case 'description.codeUT': return client.description.codeUT;
        default: return client[property];
      }
    };
  }

完成结果

import {AfterContentInit, AfterViewInit, Component, Input, OnInit, ViewChild} from '@angular/core';
import {Client, ClientStatus} from '@models/client.model';
import {ClientService} from '@services/client.service';
import {MatSort, Sort} from '@angular/material/sort';
import {MatTableDataSource} from '@angular/material/table';

@Component({
  selector: 'app-table-entries',
  templateUrl: './table-entries.component.html',
  styleUrls: ['./table-entries.component.scss']
})
export class TableEntriesComponent implements OnInit{
  displayedColumns: string[] = ['expectedDate', 'description.id', 'priority' ];
  @ViewChild(MatSort, {static: true}) sort: MatSort;
  sortableEntries: MatTableDataSource<Client>;

  @Input() set entries( data: Client[] ) {
    this.setTableDataSource(data);
  }

  setTableDataSource(data: any) {
    this.sortableEntries = new MatTableDataSource<any>(data);
    this.sortableEntries.sort = this.sort;
    this.sort.active = 'expectedDate';
    this.sort.direction = 'asc';
    this.sortableEntries.sortingDataAccessor = ( client, property) => {
      switch ( property ) {
        case 'description.id': return client.description.id;
        default: return client[property];
      }
    };
  }

  constructor( clientService: ClientService ) {
    this.sortableEntries = new MatTableDataSource<Client>( this.entries );
  }
  ngOnInit(): void {
    console.dir( this.entries );
  }

}