Angular Material MatPaginator показывает страницу 0 из 0

заранее извините за вопрос. Я погуглил свою проблему, прежде чем писать это, и перепробовал множество решений, но безуспешно. Я новичок в Angular, пытающийся изучить Material. Мой простой проект делает http-запрос и использует полученный JSON для заполнения таблицы. Таблица Angular Material работает нормально, а paginator - нет. Он отображается серым цветом и показывает страницу 0 из 0.

Компонент .html выглядит следующим образом:

<div style="height: 80vh;">
  <mat-toolbar color="primary">
    <mat-toolbar-row>
      <button mat-icon-button (click)="sidenav.toggle()" fxShow="true" fxHide.gt-sm>
        <mat-icon>menu</mat-icon>
      </button>
      <span>Teste - Requisição Http/Tabela</span>
      <span class="menu-spacer"></span>
    </mat-toolbar-row>
  </mat-toolbar>

  <mat-sidenav-container fxFlexFill>
    <mat-sidenav #sidenav>
      <mat-nav-list>
        <a (click)="sidenav.toggle()" mat-list-item>Fechar</a>
        <a href="#" mat-list-item>Link 1</a>
        <a href="#" mat-list-item>Link 2</a>
        <a href="#" mat-list-item>Link 3</a>
      </mat-nav-list>
    </mat-sidenav>
    <mat-sidenav-content fxFlexFill>
      <table mat-table [dataSource]="dataSource" class="mat-elevation-z8">

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

        <ng-container matColumnDef="email">
          <th mat-header-cell *matHeaderCellDef> Email </th>
          <td mat-cell *matCellDef="let element"> {{element.email}} </td>
        </ng-container>

        <ng-container matColumnDef="first_name">
          <th mat-header-cell *matHeaderCellDef> First Name </th>
          <td mat-cell *matCellDef="let element"> {{element.first_name}} </td>
        </ng-container>

        <ng-container matColumnDef="last_name">
          <th mat-header-cell *matHeaderCellDef> Last Name </th>
          <td mat-cell *matCellDef="let element"> {{element.last_name}} </td>
        </ng-container>

        <ng-container matColumnDef="avatar">
          <th mat-header-cell *matHeaderCellDef> Avatar </th>
          <td mat-cell *matCellDef="let element"> {{element.avatar}} </td>
        </ng-container>

        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
      </table>
      <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" showFirstLastButtons></mat-paginator>
    </mat-sidenav-content>
  </mat-sidenav-container>
</div>

Компонент .ts выглядит следующим образом:

import { HttpClient } from '@angular/common/http';
import { AfterViewInit, Component, ViewChild } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';

export interface UserData {
  id: number;
  email: string;
  first_name: string;
  last_name: string;
  avatar: string;
}

const USER_DATA: UserData[] = [];

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
  title = 'Test';
  url = 'https://reqres.in/api/users?page=1';
  displayedColumns: string[] = ['id', 'email', 'first_name', 'last_name', 'avatar'];
  dataSource = new MatTableDataSource<UserData>(USER_DATA);
 
  constructor(private http: HttpClient) {
  
    this.http.get(this.url).toPromise().then(data => {
      console.log(data["data"]);
      this.dataSource = data["data"]
      console.log(this.dataSource)
    });
  }

  @ViewChild(MatPaginator) paginator: MatPaginator;

  ngAfterViewInit() {
    this.dataSource.paginator = this.paginator;
  }
}

Что я делаю не так? Спасибо


person met4lz    schedule 01.12.2020    source источник


Ответы (3)


Попробуйте добавить #paginator в

<mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" showFirstLastButtons></mat-paginator>

Так должно быть:

<mat-paginator #paginator [pageSizeOptions]="[5, 10, 25, 100]" showFirstLastButtons></mat-paginator>

Без идентификатора #paginator декоратор @ViewChild никогда не сможет найти элемент (этот идентификатор должен быть таким же, как используемый в строке декоратора @ViewChild). Эта маленькая деталь не включена в пример Pagination в документации Angular Material (или я не смог ее увидеть..)

Кроме того, попробуйте объявить объект dataSource как:

dataSource! = MatTableDataSource<UserData>;

вместо

dataSource = new MatTableDataSource<UserData>(USER_DATA);

Затем, когда обещание будет разрешено, назначьте содержимое таким образом

this.dataSource = new MatTableDataSource<UserData>(data.data);

вместо

this.dataSource = data["data"]

Сразу после этого назначаем компонент paginator на dataSource.paginator:

this.dataSource.paginator = this.paginator;

person DRFredy    schedule 13.02.2021
comment
Пробовал, но все равно не получилось. Спасибо, в любом случае - person met4lz; 22.02.2021
comment
я обновил ответ - person DRFredy; 23.02.2021

В документации angular забыли добавить, что вам нужно определить { static: false} или {static: true} .

Как это:

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

в документах:

static — значение True для разрешения результатов запроса до запуска обнаружения изменений, значение false для разрешения после обнаружения изменений. По умолчанию ложно.

Вам нужно установить его в false, если вы хотите использовать значение по умолчанию.

person Becike    schedule 01.12.2020
comment
Спасибо за быстрый бекике, но к сожалению все равно не получилось. Пагинатор по-прежнему показывает страницу 0 из 0 - person met4lz; 02.12.2020
comment
А если попробовать поместить ‹table› и ‹mat-paginator› в div? Стоит попробовать... Мат-стол иногда может быть хитрым... - person Becike; 02.12.2020
comment
Не повезло и с помещением их в div =( - person met4lz; 02.12.2020
comment
У меня есть еще одна идея: попробуйте применить paginator после того, как вы получили данные в своем промисе. - person Becike; 02.12.2020
comment
Кстати, я обычно создаю новый MatTableDataSource, когда получаю ответ от наблюдаемого (httpClient), и сразу же добавляю paginator - person Becike; 02.12.2020

Попробуйте удалить AfterView и заменить ViewChild кодом ниже:

@ViewChild(MatPaginator) set matPaginator(paginator: MatPaginator) {
    this.dataSource.paginator = paginator;
}
person Kent    schedule 21.02.2021
comment
Вы имеете в виду удаление implements AfterViewInit и ngAfterViewInit() { this.dataSource.paginator = this.paginator; } ? - person met4lz; 22.02.2021
comment
Да, не реализуйте AfterViewInit и полностью удалите ngAfterViewInit() {...}. Затем замените это: @ViewChild(MatPaginator) paginator: MatPaginator; с кодом, который я предложил. - person Kent; 25.02.2021