Custom Table Pagination with Checkbox Field update in Lightning Component

By | August 8, 2020

ApexClass:

public class PaginationContactCtrl {
    @AuraEnabled 
    public static List<contactListWrapper> fetchContactWrapper(){     
        List<contactListWrapper> lstcontactListWrapper = new List<contactListWrapper>();
        for(Contact con : [Select id,LastName,Email,Phone,Active__c
                           From Contact
                           Limit 2000]){
                               lstcontactListWrapper.add(new contactListWrapper(false,con));
                           } 
        return lstcontactListWrapper; 
    }
    public class contactListWrapper {
        @AuraEnabled public boolean isChecked {get;set;}
        @AuraEnabled public  contact objContact{get;set;}
        public contactListWrapper(boolean isChecked, contact objContact){
            this.isChecked = isChecked;
            this.objContact = objContact;
        }
    }
    @AuraEnabled
    public static void updateRecord(List <String> lstRecordId) {
        List<Contact> lstUpdate = new List<Contact>();
        for(Contact con : [SELECT id,LastName,Email,Phone,Active__c FROM Contact WHERE Id IN : lstRecordId]){
            con.Active__c = true; 
            lstUpdate.add(con);
        }
        if(lstUpdate.size() > 0){
            update lstUpdate;
        }
    }
}

Lightning Component:

<aura:component controller="PaginationContactCtrl" implements="force:hasRecordId,force:appHostable,flexipage:availableForAllPageTypes" access="global" >
    
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:handler event="force:refreshView" action="{!c.doInit}" />
    <aura:attribute name="listOfAllContacts" type="list"/> 
    <aura:attribute name="PaginationList" type="list"/> 
    <aura:attribute name="selectedContacts" type="list"/> 
    <aura:attribute name="selectedCount" type="integer" default="0"
                    description="selected Records Count"/>
    <aura:attribute name="startPage" type="Integer" />
    <aura:attribute name="endPage" type="Integer"/>
    <aura:attribute name="totalRecordsCount" type="Integer"/>
    <aura:attribute name="pageSize" type="Integer" default="10"
                    description="number of records to be display on per page"/>
    <aura:attribute name="currentPage" type="integer" default="1"/>
    <aura:attribute name="totalPagesCount" type="integer"/>
    <aura:attribute name="bNoRecordsFound" type="boolean"/>
    
    <aura:if isTrue="{!v.bNoRecordsFound}">
        <div class="slds-notify slds-notify_alert slds-theme_alert-texture slds-theme_info" role="alert">
            <span class="slds-assistive-text">error</span>
            <h2>No record found.</h2>
        </div>
        <aura:set attribute="else">
            
            <!-- display total record and selected record count -->    
            <p class="slds-m-around_small">
                <span class="slds-badge slds-badge_lightest" style="display:inline-block">
                    Total Records : {!v.selectedCount > 0 ? v.selectedCount + '/' : ''} {!v.totalRecordsCount} 
                </span>
            </p>
            <div class="slds-align_absolute-center">
                <lightning:button variant="success"
                                  label="Update Field"
                                  onclick="{!c.updateFields}"
                                  disabled="{!v.selectedCount == 0}"/>
            </div>
            <br/>
            <!-- Custom Table start-->  
            <table class="slds-table slds-table_bordered slds-table_cell-buffer">
                <thead>
                    <tr class="slds-text-title_caps">
                        <!--header checkbox for select all-->
                        <th style="width:3.25rem;" class="slds-text-align_right">
                            <div class="slds-form-element">
                                <div class="slds-form-element__control">
                                    <label class="slds-checkbox">
                                        <ui:inputCheckbox aura:id="selectAllId"
                                                          change="{!c.selectAllCheckbox}"/>
                                        <span class="slds-checkbox_faux"></span>
                                        <span class="slds-form-element__label"></span>
                                    </label>
                                </div>
                            </div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Name">LastName</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Phone">Phone</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Type">Email</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Active">Active</div>
                        </th>
                    </tr>
                </thead>
                <tbody>
                    <aura:iteration items="{!v.PaginationList}" var="obj">
                        <tr>
                            <th scope="row" class="slds-text-align_right" style="width:3.25rem;">
                                <div class="slds-form-element">
                                    <div class="slds-form-element__control">
                                        <label class="slds-checkbox">
                                            <ui:inputCheckbox text="{!obj.objContact.Id}"
                                                              value="{!obj.isChecked}"
                                                              change="{!c.checkboxSelect}"
                                                              aura:id="checkid"/>
                                            <span class="slds-checkbox_faux"></span>
                                            <span class="slds-form-element__label text"></span>
                                        </label>
                                    </div>
                                </div>
                            </th>
                            <th scope="row">
                                <div class="slds-truncate" title="{!obj.objContact.LastName}">
                                    {!obj.objContact.LastName}
                                </div>
                            </th> 
                            <th scope="row">
                                <div class="slds-truncate" title="{!obj.objContact.Phone}">
                                    {!obj.objContact.Phone}
                                </div>
                            </th>
                            <th scope="row">
                                <div class="slds-truncate" title="{!obj.objContact.Email}">
                                    {!obj.objContact.Email}
                                </div>
                            </th>
                            <th scope="row">
                                <div class="slds-truncate" title="{!obj.objContact.Active__c}">
                                    <ui:outputCheckbox value="{!obj.objContact.Active__c}" />
                                </div>
                            </th>
                        </tr>
                    </aura:iteration>
                </tbody>
            </table>
            <!-- Custom Table End -->
            <br/>
            <!--  Pagination Buttons Start -->
            <div class="slds-align_absolute-center">  
                <lightning:button label="First" disabled="{!v.startPage == 0}"  onclick="{!c.firstpage}" variant="brand"/>
                <lightning:button label="Previous"
                                  disabled="{!v.startPage == 0}"  
                                  onclick="{!c.navigation}"
                                  variant="brand"
                                  iconName="utility:back"
                                  name="previous"/>
                <span class="slds-badge slds-badge_lightest"
                      style="margin-right: 10px;margin-left: 10px;">
                    Page {!v.currentPage} out of {!v.totalPagesCount}
                </span>
                <lightning:button label="Next"
                                  disabled="{!(v.endPage + 1) >= v.totalRecordsCount}" 
                                  onclick="{!c.navigation}"
                                  variant="brand"
                                  iconName="utility:forward"
                                  iconPosition="right"
                                  name="next"/>
                <lightning:button label="Last" disabled="{!v.endPage >= v.totalRecordsCount}" onclick="{!c.lastpage}" variant="brand"/>
                <!--  Pagination Buttons End -->
            </div>  
        </aura:set> 
    </aura:if>
</aura:component>

JS Controller:

({
    doInit: function(component, event, helper) {
        helper.doInitHelper(component, event);
    },
    firstpage: function (component,event,helper) {
        component.set("v.currentPage", 0);
        helper.first(component);
    },
    lastpage: function (component,event,helper) {
        var pageNumber = component.get("v.totalPagesCount");
        component.set("v.currentPage", pageNumber);
        helper.last(component);
    },
    
    navigation: function(component, event, helper) {
        var sObjectList = component.get("v.listOfAllContacts");
        var end = component.get("v.endPage");
        var start = component.get("v.startPage");
        var pageSize = component.get("v.pageSize");
        var whichBtn = event.getSource().get("v.name");
        // check if whichBtn value is 'next' then call 'next' helper method
        if (whichBtn == 'next') {
            component.set("v.currentPage", component.get("v.currentPage") + 1);
            helper.next(component, event, sObjectList, end, start, pageSize);
        }
        // check if whichBtn value is 'previous' then call 'previous' helper method
        else if (whichBtn == 'previous') {
            component.set("v.currentPage", component.get("v.currentPage") - 1);
            helper.previous(component, event, sObjectList, end, start, pageSize);
        }
    },
    
    selectAllCheckbox: function(component, event, helper) {
        var selectedHeaderCheck = event.getSource().get("v.value");
        var updatedAllRecords = [];
        var updatedPaginationList = [];
        var listOfAllContacts = component.get("v.listOfAllContacts");
        var PaginationList = component.get("v.PaginationList");
        
        // play a for loop on all records list 
        for (var i = 0; i < listOfAllContacts.length; i++) {
            // check if header checkbox is 'true' then update all checkbox with true and update selected records count
            // else update all records with false and set selectedCount with 0  
            if (selectedHeaderCheck == true) {
                listOfAllContacts[i].isChecked = true;
                component.set("v.selectedCount", listOfAllContacts.length);
            } else {
                listOfAllContacts[i].isChecked = false;
                component.set("v.selectedCount", 0);
            }
            updatedAllRecords.push(listOfAllContacts[i]);
        }
        // update the checkbox for 'PaginationList' based on header checbox 
        for (var i = 0; i < PaginationList.length; i++) {
            if (selectedHeaderCheck == true) {
                PaginationList[i].isChecked = true;
            } else {
                PaginationList[i].isChecked = false;
            }
            updatedPaginationList.push(PaginationList[i]);
        }
        component.set("v.listOfAllContacts", updatedAllRecords);
        component.set("v.PaginationList", updatedPaginationList);
    },
    
    checkboxSelect: function(component, event, helper) {
        // on each checkbox selection update the selected record count 
        var selectedRec = event.getSource().get("v.value");
        var getSelectedNumber = component.get("v.selectedCount");
        if (selectedRec == true) {
            getSelectedNumber++;
        } else {
            getSelectedNumber--;
            component.find("selectAllId").set("v.value", false);
        }
        component.set("v.selectedCount", getSelectedNumber);
        // if all checkboxes are checked then set header checkbox with true   
        if (getSelectedNumber == component.get("v.totalRecordsCount")) {
            component.find("selectAllId").set("v.value", true);
        }
    },
    /* Update field for selected records */
    updateFields: function(component, event, helper) {
        var allRecords = component.get("v.listOfAllContacts");
        var selectedRecords = [];
        for (var i = 0; i < allRecords.length; i++) {
            if (allRecords[i].isChecked) {
                selectedRecords.push(allRecords[i].objContact.Id);
            }
        }
        component.set('v.selectedContacts', selectedRecords);
        var action = component.get("c.updateRecord");      
        action.setParams({ lstRecordId : component.get('v.selectedContacts') });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                console.log(state);
                $A.get('e.force:refreshView').fire();
               component.set("v.currentPage", 0);
            }
        });
        $A.enqueueAction(action);
    },
})

Helper:

({
    /* doInitHelper funcation to fetch all records, and set attributes value on component load */
    doInitHelper : function(component,event){ 
        var action = component.get("c.fetchContactWrapper");
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS"){
                var oRes = response.getReturnValue();
                if(oRes.length > 0){
                    component.set('v.listOfAllContacts', oRes);
                    var pageSize = component.get("v.pageSize");
                    var totalRecordsList = oRes;
                    var totalLength = totalRecordsList.length ;
                    component.set("v.totalRecordsCount", totalLength);
                    component.set("v.startPage",0);
                    component.set("v.endPage",pageSize-1);
                    
                    var PaginationLst = [];
                    for(var i=0; i < pageSize; i++){
                        if(component.get("v.listOfAllContacts").length > i){
                            PaginationLst.push(oRes[i]);    
                        } 
                    }
                    component.set('v.PaginationList', PaginationLst);
                    component.set("v.selectedCount" , 0);
                    //use Math.ceil() to Round a number upward to its nearest integer
                    component.set("v.totalPagesCount", Math.ceil(totalLength / pageSize));  
                    
                }else{
                    // if there is no records then display message
                    component.set("v.bNoRecordsFound" , true);
                } 
            }
            else{
                alert('Error...');
            }
        });
        $A.enqueueAction(action);  
    },
    
    next : function(component,event,sObjectList,end,start,pageSize){
        var Paginationlist = [];
        var counter = 0;
        for(var i = end + 1; i < end + pageSize + 1; i++){
            if(sObjectList.length > i){ 
                if(component.find("selectAllId").get("v.value")){
                    Paginationlist.push(sObjectList[i]);
                }else{
                    Paginationlist.push(sObjectList[i]);  
                }
            }
            counter ++ ;
        }
        start = start + counter;
        end = end + counter;
        component.set("v.startPage",start);
        component.set("v.endPage",end);
        component.set('v.PaginationList', Paginationlist);
    },
    
    previous : function(component,event,sObjectList,end,start,pageSize){
        var Paginationlist = [];
        var counter = 0;
        for(var i= start-pageSize; i < start ; i++){
            if(i > -1){
                if(component.find("selectAllId").get("v.value")){
                    Paginationlist.push(sObjectList[i]);
                }else{
                    Paginationlist.push(sObjectList[i]); 
                }
                counter ++;
            }else{
                start++;
            }
        }
        start = start - counter;
        end = end - counter;
        component.set("v.startPage",start);
        component.set("v.endPage",end);
        component.set('v.PaginationList', Paginationlist);
    },
    first: function(cmp){
        var sObjectList = cmp.get("v.listOfAllContacts");
        var end = cmp.get("v.endPage");
        var start = cmp.get("v.startPage"); // 0
        var pageSize = cmp.get("v.pageSize"); //10
        var Paginationlist = [];
        
        for(var i=0; i< pageSize-1; i++){
            if(cmp.get("v.listOfAllContacts").length> i){
                Paginationlist.push(sObjectList[i]);
            }
        }
        cmp.set("v.startPage",0);
        cmp.set("v.endPage",pageSize-1);
        cmp.set('v.PaginationList', Paginationlist);
    },
    last: function(cmp){
        var sObjectList = cmp.get("v.listOfAllContacts");
        var totalrec = cmp.get("v.totalRecordsCount");
        var end = cmp.get("v.endPage");
        var start = cmp.get("v.startPage"); // 0
        var pageSize = cmp.get("v.pageSize"); //10
        var Paginationlist = [];
        
        for(var i=totalrec-pageSize; i< totalrec; i++){
            if(cmp.get("v.listOfAllContacts").length> i){
                Paginationlist.push(sObjectList[i]);
            }
        }
        cmp.set("v.startPage",totalrec-pageSize);
        cmp.set("v.endPage",totalrec);
        cmp.set('v.PaginationList', Paginationlist);
    },
    
})

Application:

<aura:application extends="force:slds">
    <c:PaginationContact/>
</aura:application>

Output:

Share this...
Share on Facebook
Facebook
Email this to someone
email

Leave a Reply

Your email address will not be published. Required fields are marked *