MatSort и MatPaginator не инициализируются с использованием @ViewChild и ngAfterViewInit, если внутри * ngIf

Я использую матовую таблицу с пагинатором и сортирую в *ngIf. Данные таблицы извлекаются с помощью API.

Это машинописный код компонента:

export class UserPermissionAdminComponent implements AfterViewInit, OnInit {

  dataSource: MatTableDataSource<UserPermission> = new MatTableDataSource<UserPermission>();
  columnsToDisplay: string[] = ['id', 'name'];

  @ViewChild(MatSort, { static: false }) sort!: MatSort;
  @ViewChild(MatPaginator, { static: false }) paginator!: MatPaginator;

  constructor(private userPermService: UserPermissionService) {
  }

  ngOnInit(): void {
    this.userPermService.getAllUserPermissions()
      .subscribe(recvPerms => this.dataSource.data = recvPerms);
  }

  ngAfterViewInit(): void {
    this.dataSource.sort = this.sort;
    this.dataSource.paginator = this.paginator;
    console.log(this.dataSource.sort);
  }

  applyFilter(event: Event): void {
    const filterValue = (event.target as HTMLInputElement).value;
    this.dataSource.filter = filterValue.trim().toLowerCase();
  }

}

А это шаблон компонента:


<div class="container">
  <h2>Permisiuni utilizatori</h2>

  <ng-container *ngIf="dataSource.data.length; then existingPermissions; else noPermissions">
  </ng-container>

  <ng-template #existingPermissions>
    <div>
      <div class="filter-container">
        <mat-form-field>
          <mat-label>Cautare</mat-label>
          <input matInput (keyup)="applyFilter($event)" placeholder="Ex: READ" #input />
        </mat-form-field>
      </div>
      
      <div class="table-container mat-elevation-z8">
        <table mat-table [dataSource]="dataSource" matSort>
          <ng-container matColumnDef="id">
            <th mat-header-cell *matHeaderCellDef mat-sort-header> ID </th>
            <td mat-cell *matCellDef="let permission"> {{permission.id}} </td>
          </ng-container>
          <ng-container matColumnDef="name">
            <th mat-header-cell *matHeaderCellDef mat-sort-header> Denumire permisiune </th>
            <td mat-cell *matCellDef="let permission"> {{permission.name}} </td>
          </ng-container>
          <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
          <tr mat-row *matRowDef="let rowData; columns: columnsToDisplay"></tr>
        </table>
        <mat-paginator [pageSizeOptions]="[5, 10, 20]"></mat-paginator>
      </div>
    </div>
  </ng-template>

  <ng-template #noPermissions>
    <div>
      <span class="notification">Nu a fost gasita nicio permisiune utilizator.</span>
    </div>
  </ng-template>
</div>

Проблема в том, что сортировка и разбивка на страницы не работают (в console.log также указано, что this.sort равно undefined). Таблица содержит все данные на одной странице. Фильтрация тоже работает.


person Vlad    schedule 28.12.2020    source источник


Ответы (1)


Мне удалось исправить проблему, добавив сеттеры в пагинатор и сортируя:

@ViewChild(MatSort, { static: false }) set sort(val: MatSort) {
    if (val) {
      this.dataSource.sort = val;
    }
  }

  @ViewChild(MatPaginator, { static: false }) set paginator(val: MatPaginator) {
    if (val) {
      this.dataSource.paginator = val;
    }
  }

Однако теперь код работает даже без ngAfterViewInit. Может кто-нибудь объяснить, как и почему это работает?

person Vlad    schedule 28.12.2020