19

I have replicated thsi case: Angular 5 Material Table not getting data from service

But when I try access any property from paginator I get undefined error from this objet.

Any ideas?

Thanks

Kram_
  • 763
  • 2
  • 6
  • 12

13 Answers13

71

I got the same issue. Placing mat-paginator tag outside *ngIf resolved my issue. Make sure it is available to component class without any conditions.

Pranav Pavan
  • 734
  • 6
  • 4
17

Some issues that may cause mat-paginator is undefined:

  1. You forgot to import in app.module.ts import { MatPaginatorModule } from '@angular/material'; and then declare the import in the imports array inside ngModule.

    @NgModule({ declarations: [ somestuff], imports: [ MatPaginatorModule]});

  2. Import MatPaginator inside the component you are using: import {MatPaginator, MatSort, MatTableDataSource} from '@angular/material';

  3. set the MatDataSource to be none. (only need to do this if you are going to be getting async data e.g. from a server)

    this.dataSource = new MatTableDataSource([]);

  4. Make sure you set the length property of the mat-paginator to the length of the data rows returned.

  5. Set the paginator inside NgAfterViewInit method or if that doesn't work try:

private paginator: MatPaginator; private sort: MatSort;

@ViewChild(MatSort) set matSort(ms: MatSort) {
    this.sort = ms;
    this.setDataSourceAttributes();
}

@ViewChild(MatPaginator) set matPaginator(mp: MatPaginator) {
    this.paginator = mp;
    this.setDataSourceAttributes();
}

setDataSourceAttributes() {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;

    if (this.paginator && this.sort) {
        this.applyFilter('');
    }
}
Josh Dando
  • 1,647
  • 14
  • 9
5

In some cases, the issue is related to conditional outer div. Ex:

<div *ngIf="condition">
    ...

   <mat-paginator ....>
</div>

For a such scenario just replace *ngIf="condition" with [hidden]="!condition" and it'll work. Please refer to https://github.com/angular/components/issues/10205 for more details

Youness Marhrani
  • 1,084
  • 16
  • 8
5

I had a similar problem and this is how I got it working:

My Initial Code Setup

component.html

    <div class="chart-wrapper" *ngIf="viewType === 'chart'; else table;">
        // Load Chart Here
    </div>

    <ng-template #table>
        // Load Table Here

        <mat-paginator
            #paginator
            [length]="tableDataSource.data ? tableDataSource.data.length : 0"
            [pageSize]="pageSize"
            [pageSizeOptions]="pageSizeOptions"
            (page)="onPageChange($event)"
        ></mat-paginator>
    </ng-template>

component.ts

columns: string[] = [];
tableDataSource: MatTableDataSource<any[]> = new MatTableDataSource([]);
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
pageIndex = 0;
pageSize = 10;
pageSizeOptions = [10, 15, 20];

ngOnInit() {
    this.getTableData();
}

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

getTableData() {
    // After getting data from API
    this.tableDataSource.data = apiResponse;
}

The Solution

Put static: false while declaring Mat Paginator

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

and then set paginator onto tableDataSource after data gets loaded into it

this.tableDataSource.data = apiResponse;
this.tableDataSource.paginator = this.paginator;

Thanks to the solution by cisco336 on this thread

To my surprise nobody appraised that solution.

Pradeep Vig
  • 485
  • 6
  • 7
4

For me it was broken after angular upgrade from 7 to any version(although i checked in only angular 12). In Angular 8 they introduced a parameter where we are supposed to give {static: true} if we need the value in ngOninit. From Angular 9 it was set to false by default if we are not mentioning it explicitly.

So changing code from this @ViewChild(MatPaginator) paginator: MatPaginator;

To this @ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;

Fixed my issue.

Saiteja Samala
  • 111
  • 2
  • 7
2

"Inserting an *ngIf means that its contents cannot be queried until the view is initialized with change detection. This means the query for sort is empty at ngOnInit.

This can be resolved by changing the setup from ngOnInit to ngAfterViewInit. https://stackblitz.com/edit/angular-mewfek?file=src/app/app.component.ts "

reference https://github.com/angular/components/issues/15966

hunterTR
  • 190
  • 6
2

In my case, paginator object was getting initiated in ngOnInit() and giving exception paginator is undefined.

Initial code i.e. not working code:

ngOnInit() {
    this.dataSource = new StoreServiceDataSource<User>(this.userService, this.snackBar);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
}

After correction i.e. working code:

ngAfterViewInit() {
    this.dataSource = new StoreServiceDataSource<User>(this.userService, this.snackBar);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
}

Just changed initializing life cycle hook. Earlier paginator was getting initialized in hgOnInit(), now it's initialized in ngAfterViewInit().

Shailesh Vikram Singh
  • 1,433
  • 17
  • 26
1

[length]="dataSource.filteredData.length" over "mat-paginator" worked for me.

<mat-paginator [pageSize]="10" [pageSizeOptions]="[10,25,50]" #paginator [length]="dataSource.filteredData.length"[showFirstLastButtons]="true"></mat-paginator>

Milton
  • 11
  • 1
  • 5
0

MatPaginator being undefined most likely means you do not have the module imported. Sometimes angular mat does not explicitly tell you these things that you are missing. But always check the API tab under their documentation before using a component. At your module level, you should have the following in your app.module.ts file.

the import

import { MatButtonModule, MatTableModule, MatPaginatorModule, MatProgressSpinnerModule, MatTableDataSource } from '@angular/material';

Your component imported that used paginator of course

import { TableComponent } from './table/table.component';

Those modules imported in your imports array

imports: [
    BrowserAnimationsModule,
    NgbModule.forRoot(),
    FormsModule,
    RouterModule,
    AppRoutingModule,
    CommonModule,
    MatButtonModule,
    MatTableModule,
    BrowserAnimationsModule,
    MatPaginatorModule,
    MatProgressSpinnerModule,
    HttpClientModule
],

And those modules exported if necessary (different topic so I wont discuss here).

exports: [
    MatButtonModule,
    MatTableModule,
    MatPaginatorModule
],

This is all happening in my App.Module

export class AppModule { }

This assuming you do bot have your project structured as feature modules. In that case you would really only need everything I talked about in the module in which your component lives. But in this case, where everything is under the app module, this works just fine.

doedotdev
  • 555
  • 4
  • 17
0
<div class="  fixed-form-bottom" [hidden]="changeState">
  <div class="team-footer">
    <mat-paginator #paginator [pageSize]="pageSize" [showFirstLastButtons]="true" [length]="totalSize"
      [pageIndex]="currentPage" (page)="pageEvent = handlePage($event)" [hidePageSize]="true">
    </mat-paginator>
  </div>
</div>

And in .ts file , you compare your condition and pass true/ false from there

if(this.totalSize>3){
  this.changeState=true;

}

its worked for me

B.Nishan
  • 536
  • 4
  • 13
0

Check if you have *ngIf that wrap your mat-paginator or any top component, if you need hide you should use [hidden] attribute in your component

rlchavezc
  • 68
  • 2
  • 9
0

Another reason for the delay in pagination injection is one or more missing end tag such as within your html markup, which seems to impact the timing of the pagination markup DOM injection.

In this type of problem scenario a 2nd+ load of the table will show the pagination components.

Peter O Brien
  • 105
  • 2
  • 6
0

There are two solutions to this problem

Solution 1: If mat-paginator is inside *ngIf then either take it outside or use [hidden] attribute.

<div [hidden]="condition">
</div>

Solution 2: Make sure you are not using static: true while initializing the paginator

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

change it to

@ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;
Hari Das
  • 10,145
  • 7
  • 62
  • 59