93 votes

Angular MatPaginator ne fonctionne pas

J'ai 2 composants. La pagination fonctionne pour un composant mais pas pour l'autre bien que le code soit similaire. Voici mon code html :

<div class="mat-elevation-z8">

    <mat-table [dataSource]="dataSource" matSort>

      <ng-container matColumnDef="col1">
        <mat-header-cell *matHeaderCellDef mat-sort-header> Column1 </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.col1}} </mat-cell>
      </ng-container>

      <ng-container matColumnDef="col2">
        <mat-header-cell *matHeaderCellDef mat-sort-header> Column2 </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.col2}} </mat-cell>
      </ng-container>

      <!-- Different columns goes here -->

      <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
      <mat-row *matRowDef="let row; columns: displayedColumns;">
      </mat-row>
    </mat-table>

    <mat-paginator #scheduledOrdersPaginator [pageSizeOptions]="[5, 10, 20]"></mat-paginator>
  </div>

Et ci-dessous est mon code dans component.ts :

dataSource: MatTableDataSource<any>;
displayedColumns = ['col1', 'col2', ... ];
@ViewChild('scheduledOrdersPaginator') paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
ngOnInit(): void {
    // Load data
    this.dataSource = new MatTableDataSource(somearray);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
}

Un code similaire fonctionne pour l'autre composant et la table est rendue avec la pagination correctement, aucune idée de ce qui ne va pas avec ce code.

Toute aide serait vraiment appréciée.

168voto

Skylar Brown Points 472

Dans mon cas, le <mat-paginator> se trouvait à l'intérieur d'un conteneur ayant un élément *ngIf sur celui-ci, qui n'a pas été rendu jusqu'à ce que les données soient chargées de manière asynchrone. Cela provoque this.paginator à être undefined même dans ngAfterViewInit . Cela entraîne un échec silencieux en tant que MatTableDataSource n'a aucun problème à ce que tu mettes paginator à undefined .

La solution consistait à déplacer le <mat-paginator> en dehors de la *ngIf Conteneur d

J'espère que cela aidera quelqu'un qui se trouve dans la même situation que moi.

26 votes

Merci - c'était la solution pour moi. J'ai choisi d'utiliser [hidden] au lieu de ngIf pour que le paginateur s'affiche même s'il n'y a pas de données, mais ne s'affiche pas à l'utilisateur.

0 votes

C'était le problème dans mon cas. Intelligent !

0 votes

Réponse brillante. J'étais dans le même problème

104voto

J'ai résolu un problème similaire en entourant l'instanciation d'un délai d'attente. Essayez ceci :

setTimeout(() => this.dataSource.paginator = this.paginator);

0 votes

Idéalement, je charge les données depuis un serveur et ce code est déjà intégré dans la fonction setTimeout : this.http.get(url).subscribe(data => { setTimeout(() => { this.data= data as any[] ; this.dataSource = new MatTableDataSource(this.data) ; this.dataSource.paginator = this.paginator ; this.dataSource.sort = this.sort ; }) ; } ; }.

0 votes

Ce n'est pas un problème, essayez simplement et dites-moi si ça a marché !

2 votes

C'est le cas :) Fou ! Merci @trichetriche, mais puis-je savoir pourquoi ce comportement est si étrange ?

63voto

hopsey Points 301

Bien que la réponse choisie fonctionne et résout le problème, il s'agit toujours d'une solution de rechange. Il s'agit d'une façon plus élégante et plus appropriée de traiter le problème.

Essayez d'ajouter AfterViewInit à votre classe, puis mettez this.dataSource.paginator = this.paginator à l'intérieur de ngAfterViewInit() méthode

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

alors vous n'auriez pas à appeler la solution de contournement setTimeout .

6 votes

C'est la méthode la plus appropriée

5 votes

Cela ne fonctionne pas pour moi. Ma source de données est chargée après ngAfterViewInit, ce qui peut être la cause du problème. J'ai essayé d'initialiser la source de données d'abord, puis d'utiliser ngAfterViewInit pour définir le paginateur, mais cela n'a pas fonctionné. La seule chose que j'ai trouvée qui a fonctionné est la solution de contournement dans la réponse acceptée.

0 votes

C'est la solution que j'ai trouvée. setTimeout fonctionne de manière aléatoire. J'ai donc utilisé cette solution.

35voto

Lonely Points 1031

Immédiatement après avoir défini la source de données, invoquez ChangeDetectorRef.detectChanges() :

// First import ChangeDetectorRef & Material related stuff
import { ..., ChangeDetectorRef } from '@angular/core';
import { MatSort, MatTableDataSource, MatPaginator } from '@angular/material';

// Set properties in your component
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;

// Inject in constructor
constructor (..., private cdr: ChangeDetectorRef, ...) { ... }

// Set data source and invoke detectChanges()
this.dataSource = new MatTableDataSource (MY_DATA);
this.cdr.detectChanges();

// after that you can set other properties like
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;

2 votes

Cela fonctionne parfaitement. Une solution simple et agréable pour un problème très ennuyeux.

3 votes

Fonctionne parfaitement dans Angular 9.1.2 lorsque le tableau mat est entouré de ng-if

0 votes

Dans quel événement du cycle de vie, dois-je mettre dataSource et invoquer deleteChanges ?

9voto

Hasse Points 136

Pour que cela fonctionne, j'ai dû configurer le paginateur après que les données aient été récupérées de la source.

getVariables() {
    this.activeRoute.params.subscribe(params => {
        if (params['id'] && (params['type'] === Type.CodeList)) {
            this.dataService
                .getItems(this.currentLanguage, params['id'])
                .subscribe((items: any) => {
                    this.dataSource.data = this.items;
                    this.dataSource.paginator = this.paginator;
                })
        }
    })
}

0 votes

Étonnamment, cela a résolu mon problème. Excellent travail

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X