Kerby82
Kerby82

Reputation: 5146

Mat-Paginator not working on api based mat-table

I'm implementing a mat-table that retrieve information from an API.

The mat-table is showing data as expected.

The mat-paginator is not working.

Below the code I'm using:

Component:

import {DataService} from '../../services/data.service';
import {Component, ViewChild, AfterViewInit, OnInit} from '@angular/core';
import {MatPaginator, MatTableDataSource} from '@angular/material';



@Component({
  selector: 'app-projects',
  templateUrl: './projects.component.html',
  styleUrls: ['./projects.component.css'],

})
export class ProjectsComponent implements OnInit,AfterViewInit {
  projects: any;
  dataSource = new MatTableDataSource();
  displayedColumns: any;
  length: number;
  pageSize: number=1;
  pageSizeOptions = [1, 5, 10, 50];
  @ViewChild(MatPaginator) paginator: MatPaginator;
  constructor(private dataService: DataService) { 

  }



  ngOnInit() {
    console.log("Retrieving projects");
    this.getProjects().then(
      projects => {
        console.log("Projects retrieved", projects);
        this.projects=projects;
        this.dataSource = this.projects;
        console.log(this.dataSource);
        this.displayedColumns = [
          'prj_id',
          'title',
          'priority_id'
        ];
        this.length=this.projects.length;


      }
    ).catch(function (data){
      console.log("Rejected", data);
    });

  }

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


  getProjects(){
    let promise = new Promise((resolve, reject) => {
      this.dataService.getProjects().subscribe(
        projects => {
          resolve(projects);
        },
        error => {
          console.log("error retrieving projects");
          reject("error retrieving projects");
        }
      )
    });
    return promise;
  }

}

export interface Projects {
  prj_id: string;
  title: string;
  priority_id: number;
}

HTML VIEW:

<div fxLayout="column" fxLayoutAlign="center center" >


    <button mat-raised-button color="primary" ><mat-icon>add</mat-icon>Project</button>

</div>
<div fxLayout="row" fxLayoutWrap="wrap">

  <div fxFlex.gt-sm="100" fxFlex.gt-xs="100" fxFlex="100">
      <mat-card>
          <mat-card-content> 
              <mat-card-title backgroundColor="primary">Projects</mat-card-title>
              <div class="table-rasponsive">
                  <mat-table #table [dataSource]="dataSource">

                  <!-- Position Column -->
                  <ng-container matColumnDef="prj_id">
                    <mat-header-cell *matHeaderCellDef> ID </mat-header-cell>
                    <mat-cell *matCellDef="let element"> {{element.prj_id}} </mat-cell>
                  </ng-container>

                  <!-- Name Column -->
                  <ng-container matColumnDef="title">
                    <mat-header-cell *matHeaderCellDef> TITLE </mat-header-cell>
                    <mat-cell *matCellDef="let element"> {{element.title}} </mat-cell>
                  </ng-container>

                   <!-- Name Column -->
                   <ng-container matColumnDef="priority_id">
                      <mat-header-cell *matHeaderCellDef> PRIORITY </mat-header-cell>
                      <mat-cell *matCellDef="let element"> {{element.priority_id}} </mat-cell>
                    </ng-container>



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

                <mat-paginator  #paginator
                                [length]="length"
                                [pageSize]="pageSize"
                                [pageSizeOptions]="pageSizeOptions">
                </mat-paginator>
              </div>    
          </mat-card-content>
      </mat-card>
  </div>
</div>

Upvotes: 4

Views: 16420

Answers (6)

Sheikh Wahab Mahmood
Sheikh Wahab Mahmood

Reputation: 418

Try this and remove code from ngAfterInit()

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

Upvotes: 0

kasee nadh reddy bojja
kasee nadh reddy bojja

Reputation: 126

if you are fetching data from API, then the task is async means it will call the next steps even without completing API request, there is no data in the data source if you apply paginator without data definitely paginator won't work. if you console.log(this.paginator.paginator) you will get undefined, means your data source is not initialized, so you are not able to apply paginator to the data source

To make it work, always assign data and paginator respectively after completing API requests.

    dataSource = new MatTableDataSource();
    @ViewChild(MatPaginator) paginator: MatPaginator;
    
    ngOnInit(){
    yourService.getData().subscribe(
        (data)=>{
           this.datasource.data = data;
           this.dataSource.paginator = this.paginator;
                },
        (error)=>{}
       );
    }

// note always keep <mat-paginator> after <mat-table>

Upvotes: 3

Darshuu
Darshuu

Reputation: 511

use the below line

this.dataSource = new MatTableDataSource(this.projects);

if paginator is still not working, for Dynamically loaded table data use read argument for MatPaginator

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

this will do the job.

Upvotes: 4

boyukbas
boyukbas

Reputation: 1235

After having a lot of headaches I did figure out the problem. Check this line

this.dataSource = this.projects;

and change it with

this.dataSource.data = this.projects;

It should solve your problem. Also, ngAfterViewInit is ok, don't change it.

Upvotes: 9

Kishore Konangi
Kishore Konangi

Reputation: 554

Please try to initialize the MATPAGINATOR and MATSORT as follows and this worked for me.

public dataSource = new MatTableDataSource([]);
@ViewChild(MatSort) matSort: MatSort;

private paginator: MatPaginator;
private sort: any;

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

  @ViewChild(MatSort) set content(content: ElementRef) {
    this.sort = content;
    if (this.sort) {
      this.dataSource.sort = this.sort;
    }
  }

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

Above code checks for the paginator and sort variables and will gets set when they are undefined. Also no need to add #paginator in your HTML file.

Thanks and Regards, Kishore Kumar. K

Upvotes: 2

yer
yer

Reputation: 1532

Try this: Remove the code from ngAfterViewInit();

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

and add it in ngOnInit();

Upvotes: 1

Related Questions