Pagination in Salesforce Lightning Web Component (LWC)

Pagination in Lightning Web Component Salesforce (LWC)


In the previous EPISODE, we discussed how to to create basic salesforce lwc search result component, How to create record form, How to add lwc component inside Quick action in salesforce.

In this episode, we are going to talk about how to add pagination in your lwc component where you display your list of data in a proper manner.

What is Pagination ?

Consider an example where you have thousands of records to display.
Let's have a look at the below screen.


Please refer the list of records on the screen, where every time you need to scroll up and down. 

This approach of displaying data is no more user-friendly because every time we need to search for our data without any display format / order.

A similar approach can be used in aura components as well. 

to display the same list of data, we are using pagination approach in salesforce to have a set of records on a single page and you can easily navigate to next records with navigation buttons.

Have a look at the screen with pagination approach.


Here we have limited no. of records on a single page. This approach will also provide you easy navigation.

No it's time to have look at our today's recipe :

BEFORE
-----------------------------------------------------
-----------------------------------------------------

AFTER :
-----------------------------------------------------
Screen 1 :


Screen 2 :


-----------------------------------------------------

So basically we will have 2 different lighting web components here.

1. mainComponent (LWC Parent component)
2. paginator (LWC Child component)
3. QuoteLineController (Apex Class)

The first component will have the main data list or an actual list of data. The Second component will have divided or paginated data. 

So in today's recipe, we will create the main component which is the mainboard of this component, along with the search lookup. Whereas paginator will help you to navigate between the pages. 

For example : 
Consider an example of the above Before component where we already have all the information. But to handling this next and previous button functionality we are creating this second component for easy navigation between the set of data.

So let's get started with the cool coding Steps.....

Please read comments inside coding for understanding the logic 😊

STEP 1 : Create Apex Class QuoteLineController
-----------------------------------------------------
public with sharing class QuoteLineController {

//below method will be used in mainComponent 
@AuraEnabled(Cacheable = true)
public static List<Product2> retriveProducts(String strProdName
 {
  String query = 'SELECT  Id, Name, 
                  ProductCode FROM Product2';
//null check
  if(strProdName != null && strProdName != '') 
  {      
   String key = '%' + strProdName + '%';
   query += ' WHERE Name LIKE :key';
  }
  List<Product2> lstProd = Database.query(query);
  return lstProd;
 }
}
-----------------------------------------------------

STEP 2 : Create Parent Lightning Web Component mainComponent(NOTE : If you want to know basic LWC component please visit the first EPISODE of this LWC series)

mainComponent.html
-----------------------------------------------------
<template>
    <lightning-card 
          title="Search Product
          icon-name="standard:product">
  <lightning-layout multiple-rows="true" vertical-align="end">
  <lightning-layout-item size="12" 
            small-device-size="10" 
            medium-device-size="8" 
            large-device-size="12" 
            padding="around-small">
  <div class="slds-form-element">
   <div class="slds-form-element__control">
    <lightning-input 
              type="text" 
              value={strSearchProdName}
              label="Enter Product Name" 
              onchange={handleProductName} 
              placeholder="Search Product">
     </lightning-input>
     </div>
   </div> 
  </lightning-layout-item>
</lightning-layout><br/>
        
 <lightning-datatable 
             key-field="Id" 
             data={data} 
             columns={columns}>
</lightning-datatable>

<div class="slds-m-around_medium">
<p class="slds-m-vertical_medium content">
   Displaying {startingRecord} to 
              {endingRecord} of 
              {totalRecountCount} records.
   Page {page} of {totalPage}. </p>

//calling of child paginator component
<c-paginator 
  onprevious={previousHandler} 
  onnext={nextHandler}>
</c-paginator>

</div>
  <div class="slds-p-top_medium">
   <div class="modal-footer slds-modal__footer slds-size_1-of-1">
    <div class="forceChangeRecordTypeFooter">
     <lightning-button 
                variant="brand" 
                onclick={handleConfig} 
                value="Config" label="Config">
     </lightning-button>
    </div>
   </div>
  </div>
 </lightning-card>
</template>

-----------------------------------------------------

mainComponent.js
-----------------------------------------------------
import { LightningElement, track, wire } from 'lwc';
import { refreshApex } from '@salesforce/apex';
import serachProds from '@salesforce/apex/QuoteLineController.retriveProducts';

export default class CustomSearchInLWC extends LightningElement {
    @track data;
    @track strSearchProdName = '';
    result;
//this is initialize for 1st page
    @track page = 1; 
//it contains all the Product records.
    @track items = [];
//To display the data into datatable 
    @track data = [];
//holds column info. 
    @track columns;
//start record position per page 
    @track startingRecord = 1; 
//end record position per page
    @track endingRecord = 0; 
//10 records display per page
    @track pageSize = 10; 
//total count of record received from all retrieved records
    @track totalRecountCount = 0;
//total number of page is needed to display all records 
    @track totalPage = 0; 
//To display the column into the data table
    @track columns = [
    {
     label: 'Name',
     fieldName: 'Name',
     type: 'url',
     typeAttributes: {label: { fieldName: 'Name' }, 
                     target: '_blank'}
     }, 
    {
     label: 'Product Code',
     fieldName: 'ProductCode',
     type: 'text',
        }, 
        ];

//call the apex method and pass the search string into apex method.
    @wire(serachProds, {strProdName : '$strSearchProdName' })
    wiredProducts({ error, data }) {
        if (data) {
            this.items = data;
            this.totalRecountCount = data.length; 
            this.totalPage = Math.ceil(this.totalRecountCount / this.pageSize); 
            
//initial data to be displayed ----------->
//slice will take 0th element and ends with 10, but it doesn't include 10th element
//so 0 to 9th rows will be displayed in the table
            this.data = this.items.slice(0,this.pageSize); 
            this.endingRecord = this.pageSize;

            this.error = undefined;
          } else if (error) {
            this.error = error;
            this.data = undefined;
          }
       }
//this method is called when you clicked on the previous button 
    previousHandler() {
        if (this.page > 1) {
            this.page = this.page - 1; //decrease page by 1
            this.displayRecordPerPage(this.page);
        }
    }
//this method is called when you clicked on the next button 
    nextHandler() {
        if((this.page<this.totalPage) && this.page !== this.totalPage){
            this.page = this.page + 1; //increase page by 1
            this.displayRecordPerPage(this.page);            
        }             
    }
//this method displays records page by page
    displayRecordPerPage(page){
    this.startingRecord = ((page -1) * this.pageSize) ;
    this.endingRecord = (this.pageSize * page);
    this.endingRecord = 
 (this.endingRecord > this.totalRecountCount) ?   this.totalRecountCount : this.endingRecord; 
 this.data = this.items.slice(this.startingRecord,   this.endingRecord);
 this.startingRecord = this.startingRecord + 1;
 }    
  
   handleProductName(event) {
       this.strSearchProdName = event.target.value;
       return refreshApex(this.result);
   }   
 /* eslint-disable no-console */
 // eslint-disable-next-line no-console
//this method holds the selected product.
   handleConfig(){
   var el = this.template.querySelector('lightning-datatable');
   var selected = el.getSelectedRows();
}
}
-----------------------------------------------------

mainComponent.js-meta.xml
-----------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>47.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
        <target>lightning__AppPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>
-----------------------------------------------------

STEP 3 : Now its time to create our magical child paginator lwc component.

paginator.xml
-----------------------------------------------------
<template>
 <lightning-layout>
  <lightning-layout-item>
     <lightning-button 
           label="Previous" 
           icon-name="utility:chevronleft" 
            onclick={previousHandler}>
     </lightning-button>
   </lightning-layout-item>
     <lightning-layout-item flexibility="grow">
     </lightning-layout-item>
  <lightning-layout-item>
   <lightning-button 
         label="Next" 
         icon-name="utility:chevronright" 
         icon-position="right" 
         onclick={nextHandler}>
    </lightning-button>
  </lightning-layout-item>
 </lightning-layout>
</template>
-----------------------------------------------------

paginator.js
-----------------------------------------------------
import { LightningElement } from 'lwc';

export default class Paginator extends LightningElement {
//this method handles the previous button with the help of dispatchEvent
    previousHandler() 
    {
     this.dispatchEvent(new CustomEvent('previous'));
    }
//this method handles the Next button with the help of dispatchEvent
    nextHandler() 
    {
     this.dispatchEvent(new CustomEvent('next'));
    }
}
-----------------------------------------------------

Dispatch Event in paginator.js 
This event will help you to pass the data from parent to paginator component.
Consider an example of a bus, with which we can travel from one place to our destination. 

paginator.js-meta.xml
-----------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>46.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
        <target>lightning__AppPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>
-----------------------------------------------------

And once you are done with this finally right-click on these components and apex class and deploy source to org.

And just drag your newly created lightning component on any objects record page.

And finally you will get the below output as expected 

OUTPUT :
-----------------------------------------------------

-----------------------------------------------------

Coool 😎 !! Now you can add pagination to your existing list of data.

WOHOOO !! YOU HAVE JUST COMPLETED SALESFORCE LIGHTNING WEB COMPONENT (LWC) TO ADD PAGINATION EPISODE
If you like this salesforcekid learning platform please let me know in the Comment section...Also, Share with your salesforce folks wish you all
Happy Learning ☁️⚡️ (Learn. Help. Share.) 😊 

<< PREVIOUS



Pagination in Salesforce Lightning Web Component (LWC) Pagination in Salesforce Lightning Web Component (LWC) Reviewed by on Rating: 5

No comments:

HELP !! SHARE !! SUGGEST !!

Powered by Blogger.