Selecting multiple records with pagination in the quick action panel in LWC

June 01, 2023



What will you explore:


1 TablePagination class

2 tablePagination component

 

In this blog, we will set lightning-datatable in the quick action panel by selecting multiple records. And When the end user goes to save the record before selecting any record we will show an error toast event. We will add pagination in the footer of the quick-action-panel showing the number of pages, the number of records, and the number of the current page. User can edit and save single record amount or multiselect amount, if user edit specific record and select another record to save in case of error message will popup.

 

1 Create a class to retrieve records and show data into lighting-datatable

TablePagination.cls

 
public with sharing class TablePagination {
    public TablePagination() {
       
    }
   
    @AuraEnabled (cacheable=true)
    public static List<Account> retrieveAccounts(){
        return [SELECT Id, Name, Type, Amount__c, BillingCountry FROM Account WITH SECURITY_ENFORCED order by CreatedDate asc];
    }


    @AuraEnabled
    public static void updateAmount(Object data) {
        System.Debug(' data ' + data);
        List<Account> accs = new List<Account>();
        List<WrapperRequest> actForUpdate = (List<WrapperRequest>) JSON.deserialize(JSON.serialize(data),List<WrapperRequest>.class);
        for(WrapperRequest wr : actForUpdate)
        {
            accs.add(new Account(Id = wr.Id, Amount__c = wr.amount));
        }
        System.Debug(' actForUpdate ' + actForUpdate);
        if(accs.size() == 0)
               throw new AuraHandledException('Please select the correct record to update');
        try {
            update accs;
        }
        catch (Exception e) {
            throw new AuraHandledException(e.getMessage());
        }
    }

    public class WrapperRequest
    {
        Decimal amount;
        String id;
    }

}
 
 

2 Create tablePagination component 

tablePagination.html

<template >
  <lightning-quick-action-panel header="My action">
     
    <div class="slds-m-around_none">
        <lightning-datatable data-id="datatable" key-field="Id" data={data} columns={columns} selected-rows={selectedRows}
        onrowselection={handleRowSelection} suppress-bottom-bar="false">
        </lightning-datatable>
    </div>
   
    <div slot="footer">
      <!--  Pagination Start -->
      <div class="slds-align_absolute-center">
        <lightning-button label="Previous" icon-name="utility:chevronleft" onclick={previousHandler}
        disabled={isPreviousDisable}>
        </lightning-button>
     
        <span class="slds-badge slds-badge_lightest" style="margin-right: 10px;margin-left: 10px;">
          Displaying {startingRecord} to {endingRecord} of {totalRecountCount} records.
          Page {page} of {totalPage}.
        </span>
       
        <lightning-button label="Next" icon-name="utility:chevronright" icon-position="right" onclick={nextHandler}
        disabled={isNextDisable}>
        </lightning-button>
       
        <div style="margin-left: 10em;">
          <lightning-button variant="neutral" label="Cancel" onclick={handleClose}></lightning-button>
          <lightning-button variant="brand" label="Save" class="slds-m-left_x-small" onclick={handleSave}></lightning-button>
        </div>

      </div>
      <!--  Pagination End -->
    </div>

  </lightning-quick-action-panel>
 
</template>
 
</template>
 
 
tablePagination.js
 
 
import { LightningElement, wire } from 'lwc';
import { CloseActionScreenEvent } from 'lightning/actions';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import retrieveAccounts from '@salesforce/apex/TablePagination.retrieveAccounts';
import updateAmount from '@salesforce/apex/TablePagination.updateAmount'


const columns = [
    { label: 'Name', fieldName: 'Name' },
    { label: 'Type', fieldName: 'Type' },
    { label: 'Amount', fieldName: 'Amount__c', editable:true },
    { label: 'BillingCountry', fieldName: 'BillingCountry' },
];

export default class TablePagination extends LightningElement {
    page = 1;
    items = [];
    data = [];
    columns;
    startingRecord = 1;
    endingRecord = 0;
    pageSize = 5;
    totalRecountCount = 0;
    totalPage = 0;
    selectedRows = [];
   
    @wire(retrieveAccounts)
    wiredAccounts({ error, data }) {
        if (data) {
            this.items = data;
            this.totalRecountCount = data.length;
            this.totalPage = Math.ceil(this.totalRecountCount / this.pageSize);
            //here we slice the data according page size
            this.data = this.items.slice(0, this.pageSize);
            this.endingRecord = this.pageSize;
            this.columns = columns;
            this.error = undefined;
        } else if (error) {
            this.error = error;
            this.data = undefined;
            this.showToast(this.error, 'Error', 'Error');
        }
    }

    //press on previous button
    previousHandler() {
        if (this.page > 1) {
            this.page = this.page - 1;
            this.displayRecordPerPage(this.page);
        }
    }

    //press on next button
    nextHandler() {
        if ((this.page < this.totalPage) && this.page !== this.totalPage) {
            this.page = this.page + 1;
            this.displayRecordPerPage(this.page);
        }
    }

    //this method displays records per 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;
        this.template.querySelector('[data-id="datatable"]').selectedRows = this.selectedRows;
    }

    handleRowSelection(event) {
        let updatedItemsSet = new Set();
        // selected item for maintain.
        let selectedItemsSet = new Set(this.selectedRows);
        // List of items currently loaded for the current view.
        let loadedItemsSet = new Set();

        this.data.map((ele) => {
            loadedItemsSet.add(ele.Id);
        });

        if (event.detail.selectedRows) {
            event.detail.selectedRows.map((ele) => {
                updatedItemsSet.add(ele.Id);
            });

            updatedItemsSet.forEach((id) => {
                if (!selectedItemsSet.has(id)) {
                    selectedItemsSet.add(id);
                }
            });
        }

        loadedItemsSet.forEach((id) => {
            if (selectedItemsSet.has(id) && !updatedItemsSet.has(id)) {
                selectedItemsSet.delete(id);
            }
        });

        this.selectedRows = [...selectedItemsSet];      
    }

    async handleSave(){
        var finalData = []
        const updatedFields = this.template.querySelector('lightning-datatable').draftValues;

        if(this.selectedRows.length !== 0 && updatedFields.length !== 0){
            try{
                for(let i=0; i<this.selectedRows.length; i++){
                    for(let j=0; j<updatedFields.length; j++){
                        if(this.selectedRows[i]===updatedFields[j].Id){
                            finalData.push({id:updatedFields[j].Id, amount:updatedFields[j].Amount__c})
                        }
                    }
                }
               
                console.log('finalData:', finalData)
                //Pass edit field to updateAccountAmmount controller
                const result = await updateAmount({data:finalData})
                console.log(JSON.stringify('Apex result:', result))
                const updateMsg = JSON.stringify(result)
                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Success',
                        message: 'Record updated successfully',
                        variant: 'success'
                    })
                )
   

            }catch(error){
                console.log('catch:', error)
                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Error updating',
                        message: error.body.message,
                        variant: 'error'
                    })
                )
            }

        } else {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error',
                    message: 'No record selected or edited !',
                    variant: 'error'
                })
            )
        }
        this.handleClose();
    }

    handleClose() {
        this.dispatchEvent(new CloseActionScreenEvent());
    }
}
 
 
 
tablePagination.js-meta.xml
 
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>57.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordAction</target>
    </targets>
</LightningComponentBundle>

 

 

I hope this blog helped you!