Search code examples
angulartypescriptngx-pagination

ngx-pagination click next page not working


I've problem with pagination. When I try to click next page it does not work as expected. When I click on number to go next page it doesn't working either.

I provided the code bellow and a Demo link for your reference.

HTML

<table
      mat-table
      [dataSource]="dataSource"
      matSort
      multiTemplateDataRows
      class="mat-elevation-z8-"
    >
    <ng-container
        matColumnDef="{{ column }}"
        *ngFor="let column of columnsToDisplay | paginate: { id: 'server', itemsPerPage: 10, currentPage: p, totalItems: total }"
      ><!-- -->
      <ng-container *ngIf="column === 'select'; else notSelect">
        <th mat-header-cell *matHeaderCellDef>
          <mat-checkbox (change)="$event ? masterToggle() : null"
                        [checked]="selection.hasValue() && isAllSelected()"
                        [indeterminate]="selection.hasValue() && !isAllSelected()">
          </mat-checkbox>
        </th>
        <td mat-cell *matCellDef="let row">
          <mat-checkbox (click)="$event.stopPropagation()"
                        (change)="$event ? selection.toggle(row) : null"
                        [checked]="selection.isSelected(row)"
                        >
          </mat-checkbox>
        </td>
      </ng-container>

      <ng-container *ngIf="column.length == 11"  matColumnDef="created_at">
        <th mat-header-cell *matHeaderCellDef mat-sort-header><strong>{{ column }}</strong></th>
      </ng-container>
      <ng-container #headerSort>
        <th mat-header-cell *matHeaderCellDef><strong>{{ column }}</strong></th>
      </ng-container>

        <td
          mat-cell
          *matCellDef="let element; let i = index"
          (click)="open(element)"
          class="pointer"
        >
          <ng-container>
            {{ element.created_at|date:'dd/MM/yyyy'}}

          </ng-container>

            <p *ngIf="column.length == 7">
          {{element.state}}
          </p>
          <p>
              {{element.number}}
          </p>
          <p>
          {{element.title}}
        </p>
        </td>

      </ng-container>

     <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
      <tr
        mat-row
        *matRowDef="let element; columns: columnsToDisplay"
        class="example-element-row"
        [class.example-expanded-row]="expandedElement === element"

      ></tr>

    </table>
    <pagination-controls (pageChange)="getPage($event)" id="server" ></pagination-controls>

Component

import {ChangeDetectionStrategy, ViewChild, Input, Component } from '@angular/core';
    import {Observable, of} from 'rxjs';
    import { delay, map, tap } from 'rxjs/operators';
    import { MatTableDataSource, MatDialog, MatDialogRef, MAT_DIALOG_DATA, MatPaginator, MatSort, Sort } from '@angular/material';
    import {animate, state, style, transition, trigger} from '@angular/animations';
    import { SelectionModel } from '@angular/cdk/collections';
    import {HttpDatabase, GithubIssue} from './app.service';

    // interface IServerResponse {
    //     items: string[];
    //     total: number;
    // }

    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: [ './app.component.css' ],
      changeDetection: ChangeDetectionStrategy.OnPush
    })
    export class AppComponent  {
      data: any = [];
      selectedRowIds: string;
      element:string;
      columnsToDisplay: string[]  = ['Scoopy Name', 'Domain', 'Status', 'title'];

      selection = new SelectionModel<GithubIssue>(true, []);
      displayedColumns: string[] = ['created_at','number', 'state', 'title'];
      dataSource = new MatTableDataSource<GithubIssue>();
      @ViewChild(MatSort, {static: false}) sort: MatSort;
        p: number = 1;
        total: number;
        loading: boolean;

        constructor(private httpDatabase: HttpDatabase){ }
    marked = false;
    isAllSelected() {
        const numSelected = this.selection.selected.length;
        const idSelected = this.selection.selected;
        const numRows = this.dataSource.data.length;
        return numSelected === numRows;
      }

      masterToggle() {
        if(this.isAllSelected()){
                this.selection.clear();
                // this.isButtonEnable = true;
                this.marked = false;
            }else{
                this.dataSource.data.forEach(row => this.selection.select(row));
                // this.isButtonEnable = false;
                this.marked = true
        }

    }


        ngOnInit() {
            this.getPage('desc','created',1);
        }

        getPage(sort: string, order: string, page: number) {
           this.httpDatabase.getRepoIssues(sort, order, page).subscribe(res =>{
          console.log("TEST PAGE " +page)
          this.dataSource.data = res['items'];
           console.log(this.dataSource.data)
           this.total = this.dataSource.data.length;
           console.log(this.total)
    });
        }
    }

Solution

  • The problem

    The method getPage is defined as follow:

    getPage(sort: string, order: string, page: number) {
      // ...
    }
    

    It expects as first argument a string sort, as second argument a string order and lastly as third argument a number page.

    However you used it in the HTML as follow:

    <pagination-controls (pageChange)="getPage($event)" id="server" ></pagination-controls>
    

    Here, you provided as first argument $event which is the new page (number) selected. This is received in the getPage method as the argument sort (because it is declared as first argument), so you get undefined as value for the page argument.

    Solution

    An option would be to rearrange the order of the parameters as follow:

    getPage(page: number, sort: string, order: string, ) {
      // ...
    }
    

    If you follow this approach, remember to update the call to getPage in the ngOnInit to match the new signature:

    ngOnInit() {
        this.getPage(1, 'desc', 'created');
    }
    

    Additional notes

    Consider setting some default values for parameters order and sort so the call to getPage from the HTML doesn't need to provide them. Something like this:

    getPage(page: number, sort: string = 'desc', order: string = 'created') {
      // ...
    }
    

    Also, if you want the styling correctly working (mark the current page as selected) you need to set the value of p to the selected page as follow inside the getPage function:

    getPage(page: number, sort: string = 'desc', order: string = 'created') {
      this.p = page;
      // ...
    }
    

    Stackblitz Demo