Data Table With Multiple Navigation in LWC
I am sharing code of Data Table with multiple navigation like Next, Previous, Jump to First and Last Page, Choose particular page to navigate
dataTableWithPaginattionComboList.html
<template>
<template if:true={showSpinner}>
<lightning-spinner alternative-text="Loading" size="large"></lightning-spinner>
</template>
<template if:false={showSpinner}>
<lightning-card>
<div class="slds-text-heading_large" slot="title">
<lightning-icon icon-name="standard:contact" alternative-text="Client"></lightning-icon>
<strong class="slds-m-left_x-small">Contacts</strong>
</div>
<div slot="actions">
<lightning-input value={clientFilterQuery} onchange={handleFilter}
class="slds-m-bottom_small" type='search' placeholder="Search Client"></lightning-input>
</div>
<table class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_col-bordered" >
<thead>
<tr class="slds-line-height_reset">
<th class="" scope="col">
<div class="slds-truncate">
<span onclick={handleSort} if:true={isAsc}>Last Name ↓</span>
<span onclick={handleSort} if:false={isAsc}>Last Name ↑</span>
</div>
</th>
<th class="" scope="col">
<div class="slds-truncate">First Name</div>
</th>
<th class="" scope="col">
<div class="slds-truncate">Contact</div>
</th>
<th class="" scope="col">
<div class="slds-truncate">Email</div>
</th>
</tr>
</thead>
<tbody>
<template for:each={dataToDisplay} for:item="cli">
<tr key={cli.Id} class="slds-hint-parent">
<th data-label="Opportunity Name" scope="row">
<div class="slds-truncate" title="Cloudhub">
<a href="#" data-clid={cli.Id} tabindex="-1">{cli.FirstName}</a>
</div>
</th>
<td data-label="Account Name">
<div if:true={cli.Provider_Name__c} class="slds-truncate" title="Cloudhub">{cli.LastName}</div>
</td>
<td data-label="Close Date">
<div class="slds-truncate" title="4/14/2015">{cli.Phone}</div>
</td>
<td data-label="Prospecting">
<div class="slds-truncate" title="Prospecting">{cli.Email}</div>
</td>
</tr>
</template>
</tbody>
</table>
<div slot="footer" class="slds-align_absolute-center">
<p class='slds-m-right_small'>Showing {pageParam} of {totalRecords} rows</p>
<lightning-button label="◄◄" class='slds-m-right_small slds-p-left_small slds-border_left' disabled={isFirst} onclick={handleFirst}></lightning-button>
<lightning-button label="◄" class='slds-m-right_small' disabled={isFirst} onclick={handlePrev}></lightning-button>
<lightning-combobox
name="progress"
label="Page"
class='slds-m-right_small'
value={selectedPage}
options={pages}
onchange={handlePageChange}
variant='label-hidden'></lightning-combobox>
<lightning-button label="▶" class='slds-m-right_small' disabled={isLast} onclick={handleNext}></lightning-button>
<lightning-button label="▶▶" class='slds-p-right_small slds-m-right_small slds-border_right' disabled={isLast} onclick={handleLast}></lightning-button>
<lightning-combobox
name="progress"
label="Record to Display"
class='slds-m-right_small slds-float_right'
value={pageLimit}
placeholder="Limit"
options={pageLimitOptions}
onchange={handleLimitChange}
variant='label-hidden'></lightning-combobox>
</div>
</lightning-card>
</template>
</template>
dataTableWithPaginattionComboList.js
import { LightningElement } from 'lwc';
import getClient from '@salesforce/apex/ContactController.getContact';
export default class DataTableWithPaginattionComboList extends LightningElement {
clientFilterQuery;
showSpinner=true;
allClients; //storing all clients data. Not to be modified
allFilteredClients; //storing all filtered clients data. can be modified
paginatedClientData; //storing array of client data based on limit chunks
dataToDisplay; // storing only the data that need to be displayed
pageLimit = '10'; //number of record to display per page
pages=[{ label: '1', value: '1' }]; //pagination data (total pages)
selectedPage='1'; //current selected page
totalPages; //store total number of pages
isFisrt=true;
isLast=false;
isAsc=true; //sorting logic
totalRecords;
pageParam;
//get options for the limit dropdown
get pageLimitOptions() {
return [
{ label: 'Step: 10', value: '10' },
{ label: 'Step: 25', value: '25' },
{ label: 'Step: 50', value: '50' },
{ label: 'Step: 100', value: '100' },
];
}
connectedCallback()
{
getClient()
.then(res=>{
this.isLast=false;
this.isFirst=true;
var obj=JSON.parse(JSON.stringify(res));
obj.forEach(elem=>{
elem.search= elem.LastName.toUpperCase();
elem.sortLogic= elem.LastName.toUpperCase(); // lowercase characters have ASCII lower than uppercase characters
})
this.totalRecords=obj.length;
this.allClients=obj;
this.allFilteredClients=obj;
this.handlePagination(); //invoking the pagination logic
this.validatePagination();
this.showSpinner=false;
})
.catch(err=>{
console.log(err)
})
}
compare(a, b) {
// Use toUpperCase() to ignore character casing
const bandA = a.LastName.toUpperCase();
const bandB = b.LastName.toUpperCase();
let comparison = 0;
if (bandA > bandB) {
comparison = 1;
} else if (bandA < bandB) {
comparison = -1;
}
return comparison;
}
handleSort()
{
if(this.isAsc)
{
this.allFilteredClients=this.allClients.sort(this.compare);
this.isAsc=false;
this.handlePagination();
}
else
{
this.allFilteredClients=this.allClients.sort(this.compare).reverse();
this.isAsc=true;
this.handlePagination();
}
}
handleLimitChange(event) {
this.pageLimit = event.detail.value;
this.selectedPage='1';
this.isLast=false;
this.isFirst=true;
this.handlePagination(); //invoking the pagination logic
this.validatePagination();
}
handlePagination()
{
this.pages=[];
this.totalPages= Math.ceil(this.allFilteredClients.length / parseInt(this.pageLimit));
console.log(this.totalPages);
for(var i=1; i <= this.totalPages; i++)
this.pages.push({ label : 'Page: '+i.toString(), value : i.toString() });
var perChunk = parseInt(this.pageLimit) // items per chunk
var inputArray = this.allFilteredClients;
var result = inputArray.reduce((resultArray, item, index) => {
const chunkIndex = Math.floor(index/perChunk)
if(!resultArray[chunkIndex]) {
resultArray[chunkIndex] = [] // start a new chunk
}
resultArray[chunkIndex].push(item)
return resultArray
}, [])
this.paginatedClientData=result;
this.dataToDisplay=this.paginatedClientData[parseInt(this.selectedPage)-1];
}
handleNext()
{
if(!this.isLast)
this.selectedPage=(parseInt(this.selectedPage)+1).toString();
this.dataToDisplay=this.paginatedClientData[parseInt(this.selectedPage)-1];
this.validatePagination();
}
handlePrev()
{
if(!this.isFirst)
this.selectedPage=(parseInt(this.selectedPage)-1).toString();
this.dataToDisplay=this.paginatedClientData[parseInt(this.selectedPage)-1];
this.validatePagination();
}
handlePageChange(event)
{
this.selectedPage= event.detail.value;
this.dataToDisplay=this.paginatedClientData[parseInt(this.selectedPage)-1];
this.validatePagination();
}
handleFirst()
{
this.selectedPage='1';
this.isFirst=true;
this.isLast=false;
this.dataToDisplay=this.paginatedClientData[parseInt(this.selectedPage)-1];
this.validatePagination();
}
handleLast()
{
this.selectedPage=this.totalPages.toString();
this.isFirst=false;
this.isLast=true;
this.dataToDisplay=this.paginatedClientData[parseInt(this.selectedPage)-1];
this.validatePagination();
}
validatePagination()
{
if(parseInt(this.selectedPage) == 1)
{
this.isFirst=true;
this.isLast=false;
}
else if(parseInt(this.selectedPage) == parseInt(this.totalPages))
{
this.isFirst=false;
this.isLast=true;
}
else
{
this.isFirst=false;
this.isLast=false;
}
var end=(parseInt(this.selectedPage) * parseInt(this.pageLimit)) > this.totalRecords ? this.totalRecords : (parseInt(this.selectedPage) * parseInt(this.pageLimit));
this.pageParam=(parseInt(this.selectedPage) * parseInt(this.pageLimit) - (parseInt(this.pageLimit)-1))+' to '+end;
}
handleFilter(event)
{
this.allFilteredClients=this.allClients;
this.clientFilterQuery= event.target.value;
var __FOUND = this.allFilteredClients.filter((cli, index)=> {
if(cli.Full_Name__c.toUpperCase().includes(this.clientFilterQuery.toUpperCase()))
return true;
});
if(__FOUND == undefined || __FOUND==[])
this.allFilteredClients=this.allClients;
else
this.allFilteredClients=__FOUND;
this.handlePagination();//filtering the client list based on user input
}
}
dataTableWithPaginattionComboList.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>54.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__Tab</target>
</targets>
</LightningComponentBundle>
ContactController
public with sharing class ContactController {
@AuraEnabled(cacheable=true)
public static List<Contact> getContact(){
try {
return [select FirstName,LastName,Email,Phone from contact];
} catch (Exception e) {
throw new AuraHandledException(e.getMessage());
}
}
}