Data Table With Multiple Navigation in LWC

Data Table With Multiple Navigation in LWC

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 &#8595;</span>
                                <span onclick={handleSort} if:false={isAsc}>Last Name &#8593;</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="&#9668;&#9668;" class='slds-m-right_small slds-p-left_small slds-border_left' disabled={isFirst} onclick={handleFirst}></lightning-button>
                <lightning-button label="&#9668;" 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="&#9654;" class='slds-m-right_small' disabled={isLast} onclick={handleNext}></lightning-button>
                <lightning-button label="&#9654;&#9654;" 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());
        }
    }
}

Leave a Reply