PrimeNG DataTable server-side paging
Asked Answered
S

6

8

I'm currently working on an Angular 4 project and using the PrimeNG DataTable. So far this framework seems pretty neat, but I would like to make my paging server-side. That way I will load only 10,20,.. records at a time rather than loading all 1000+ at once..

Has anyone done this before or does anyone know a solution for this?

PS: If you don't have a solution but know a framework that does support this, please let me know!

Sherfield answered 9/8, 2017 at 14:57 Comment(0)
A
14

Looks like Lazy is what we are... looking for :) https://www.primefaces.org/primeng/table/lazy

Amand answered 28/8, 2017 at 15:52 Comment(3)
The link in the answer is outdated. This is the updated link: primefaces.org/primeng/#/table/lazyBiebel
do we actually have to know the number of total records before loading the data to the table?Siglos
Yes, It's required to apply PaginationHalfhour
S
6

With the help of Lazy Loading, we can implement server side paging, filtering and sorting on the data table.

Here is the code:

listing.html

<div class="table-responsive">
  <p-dataTable
    sortField="FileNo"
    [sortOrder]="1"
    [value]="paitientListing"
    [lazy]="true"
    [rows]="10"
    [paginator]="true"
    [rowsPerPageOptions]="[10,20]"
    [totalRecords]="totalRecords"
    (onLazyLoad)="loadPatientListing($event)"
  >
    <p-column
      field="PatientID"
      header="File No"
      [sortable]="true"
      [style]="{'width':'94px'}"
    ></p-column>
    <p-column
      field="LastName"
      [sortable]="true"
      [style]="{'width':'121px'}"
      header="Last Name"
    ></p-column>
    <p-column
      field="FirstName"
      [sortable]="true"
      [style]="{'width':'122px'}"
      header="First Name"
    ></p-column>
    <p-column styleClass="col-button" [style]="{'width':'90px'}">
      <ng-template pTemplate="header"> Action </ng-template>
      <ng-template let-paitientListing="rowData" pTemplate="body">
        <button
          type="button"
          pButton
          (click)="editPatient(paitientListing.PatientID)"
          icon="fa-pencil-square-o"
        ></button>
        <button
          type="button"
          pButton
          (click)="deletePatient(paitientListing.PatientID)"
          icon="fa-trash-o"
          class="ui-button-danger"
        ></button>
      </ng-template>
    </p-column>
  </p-dataTable>
</div>

listing.Component.ts

loadPatientListing(event) {
  this.patientFilterModel.PageSize = event.rows;
  this.patientFilterModel.RowNumber = event.first;
  this.patientFilterModel.OrderColumn = event.sortField;

  if (event.sortOrder == 1) {
    this.patientFilterModel.OrderBy = 'asc';
  } else {
    this.patientFilterModel.OrderBy = 'desc';
  }
  this.patientService.GetPatientListing(this.patientFilterModel).subscribe(
    (data) => {
      this.patientModel = data;
      this.paitientListing = this.patientModel._ListPatientListing;
      this.totalRecords = data.TotalRecords;
    },
    (error) => {
      this.loading = false;
    },
  );
}
Sesterce answered 16/9, 2017 at 5:45 Comment(2)
Can you provide some explanation for your code.. Like what is 'patientFilterModel' and what is _ListPatientListing?Lucinalucinda
Can you please update the answer considering <p-dataTable> has been replaced by <p-table>? Thanks.Biebel
S
3

FYI, p-dataTable is deprecated in version 6. PrimeFaces suggest you use TurboTable. I just had to go through the conversion. You will need to add [totalRecords]='totalRecords' [lazy]='true' (onLazyLoad)='loadPatientLazy($event)' [loading]='loading'

<p-table id='patients-grid' [value]='patients' [totalRecords]='totalRecords'
        expandableRows='true' [responsive]='true' dataKey=''
        [rows]='5' [paginator]='true' [rowsPerPageOptions]='[5,10,50]'>
    <ng-template pTemplate='header'>
        <tr>
            <th style='width: 40px;'></th>
            <th style='width: 40px;'>
                <button (click)='addItemClicked( )' pButton type='button' icon='fa fa-plus' class='ui-button-primary'></button>
            </th>
            <th style='width: 80px;' [pSortableColumn]='"PatientID"'>
                Patient I D
                <p-sortIcon [field]='PatientID'></p-sortIcon>
            </th>
            <th style='width: 250px;' [pSortableColumn]='"LastName"'>
                Last Name
                <p-sortIcon [field]='LastName'></p-sortIcon>
            </th>
            <th style='width: 250px;' [pSortableColumn]='"FirstName"'>
                First Name
                <p-sortIcon [field]='FirstName'></p-sortIcon>
            </th>
            <th style='width: 40px;'></th>
        </tr>
    </ng-template>
    <ng-template pTemplate='body' let-rowData let-columns='columns' let-expanded='expanded'>
        <tr>
            <td>
                <a href='#' [pRowToggler]='rowData'>
                    <i [ngClass]='expanded ? "pi pi-fw pi-chevron-circle-down" : "pi pi-pw pi-chevron-circle-right"' style='font-size: 1.25em'></i>
                </a>
            </td>
            <td>
                <button (click)='editItemClicked( rowData )' pButton type='button' icon='fa fa-edit' class='ui-button-primary'></button>
            </td>
            <td>{{rowData['PatientID']}}</td>
            <td>{{rowData['LastName']}}</td>
            <td>{{rowData['FirstName']}}</td>
            <td>
                <button (click)="deleteItemClicked( patient )" pButton type="button" icon="fa fa-trash" class="ui-button-danger"></button>
            </td>
        </tr>
    </ng-template>
    <ng-template let-patient pTemplate='rowexpansion'>
        <tr><td [attr.colspan]='6'>
            <div class='ui-grid ui-grid-responsive ui-fluid'>
                <div class='ui-grid-row ui-inputgroup'>
                    <div class='ui-grid-col-3 nsg-primary-color nsg-text-right'><label for='PatientID'>Patient I D:&nbsp;</label></div>
                    <div class='ui-grid-col-9' id='PatientID'>{{patient.PatientID}}</div>
                </div>
                <div class='ui-grid-row ui-inputgroup'>
                    <div class='ui-grid-col-3 nsg-primary-color nsg-text-right'><label for='LastName'>Last Name:&nbsp;</label></div>
                    <div class='ui-grid-col-9' id='LastName'>{{patient.LastName}}</div>
                </div>
                <div class='ui-grid-row ui-inputgroup'>
                    <div class='ui-grid-col-3 nsg-primary-color nsg-text-right'><label for='FirstName'>First Name:&nbsp;</label></div>
                    <div class='ui-grid-col-9' id='FirstName'>{{patient.FirstName}}</div>
                </div>
            </div>
        </td><tr>
    </ng-template>
</p-table>

Note: nsg- CSS classes are my custom classes.

Smedley answered 4/9, 2018 at 22:23 Comment(2)
Also add dataKey='createdate'Smedley
Also, make sure you're using HttpClient, Http is deprecated. Version 6 of RxJs is very different.Smedley
A
3

First of all, you don't need pagination on the p-table component so the paginator property would be false like this

<p-table
            [value]="clientList"
            [rows]="pageSize"
            [paginator]="false"
            [(selection)]="selectedClients"
            [responsive]="true"
            styleClass="p-datatable-lg p-datatable-responsive"
          >

second of all, you should use paginator component like this at below of your table

<p-table
            [value]="clientList"
            [rows]="pageSize"
            [paginator]="false"
            [(selection)]="selectedClients"
            [responsive]="true"
            styleClass="p-datatable-lg p-datatable-responsive"
          >
<!-- your content goes here !-->
</table>
   <p-paginator
            (onPageChange)="handlePagination($event)"
            [rows]="pageSize"
            [totalRecords]="totalRecords"
          ></p-paginator>  

 public handlePagination(paginationData): void {
    this.currentPage = paginationData.page + 1;
    this.filterProducts();
  }



  public filterProducts(): void {
    this.isLoading = true;
    this.subs.sink = this.productService
      .filterProducts(
        this.appId,
        this.searchedProduct,
        this.selectedLangISO2,
        this.currentPage,
        this.sortBy,
        this.sortField,
        this.pageSize,
        ...this.additionalFilters
      )
      .subscribe(
        (result) => {
})
Abiosis answered 15/9, 2021 at 6:18 Comment(0)
S
1

You could listen for the onPageChange event of the Paginator to tell you when you need to get paginator.rows of data.

Stonecrop answered 9/8, 2017 at 16:5 Comment(0)
D
0

For people who are using older version info is available on https://www.primefaces.org/primeng-4.3.0/#/datatable

loadData(event: LazyLoadEvent) {
    //event.first = First row offset
    //event.rows = Number of rows per page
    //event.sortField = Field name to sort in single sort mode
    //event.sortOrder = Sort order as number, 1 for asc and -1 for dec in single sort mode
    //multiSortMeta: An array of SortMeta objects used in multiple columns sorting. Each SortMeta has field and order properties.
    //filters: Filters object having field as key and filter value, filter matchMode as value
    //globalFilter: Value of the global filter if available
    this.cars = //do a request to a remote datasource using a service and return the cars that match the lazy load criteria
}
Demimondaine answered 25/1, 2020 at 1:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.