Saturday, April 4, 2020

Custom Sorting of Data Table on Client Side In Salesforce Lightning Web Components(lwc)

This post explains how to sort data in the custom data table in the lightning web component(lwc)

For the demo, using the account data when you click on the column header the data automatically sorted.

For sorting, I used the sort method.

Apex Class
public inherited sharing class GenericController {
    @AuraEnabled(Cacheable=true)
    public static list<Account> returnAccs(){
        return [SELECT Id, Name, Industry, Type,Phone, Rating, AccountNumber FROM Account];
    }
}


HTML Code
<template>
    <lightning-card title="Custom Sorting on Datatable in Lightning Web Components">
        <table class="slds-table slds-table--bordered slds-table--cell-buffer">
            <thead>
                <tr class="slds-text-title--caps">
                    <th data-id="Name" onclick={sortName}>
                        <a href="javascript:void(0);" class="slds-th__action slds-text-link--reset">
                            <span class="slds-assistive-text">Sort</span>
                            <span class="slds-truncate" title="Name">Name</span>
                            <div if:true={isNameSort}>
                                <div if:true={isAsc}>
                                    &#9650;
                                </div>
                                <div if:true={isDsc}>
                                    &#9660;
                                </div>
                            </div>
                        </a>
                    </th>
                    <th data-id="AccountNumber" onclick={sortAccNumber}>
                        <a href="javascript:void(0);" class="slds-th__action slds-text-link--reset">
                            <span class="slds-assistive-text">Sort</span>
                            <span class="slds-truncate" title="Type">Account Number</span>
                            <div if:true={isAccNumSort}>
                                <div if:true={isAsc}>
                                    &#9650;
                                </div>
                                <div if:true={isDsc}>
                                    &#9660;
                                </div>
                            </div>
                        </a>
                    </th>
                    <th data-id="Industry" onclick={sortIndustry}>
                        <a href="javascript:void(0);" class="slds-th__action slds-text-link--reset">
                            <span class="slds-assistive-text">Sort</span>
                            <span class="slds-truncate" title="Industry">Industry</span>
                            <div if:true={isIndustrySort}>
                                <div if:true={isAsc}>
                                    &#9650;
                                </div>
                                <div if:true={isDsc}>
                                    &#9660;
                                </div>
                            </div>
                        </a>
                    </th>
                    <th data-id="Type" onclick={sortType}>
                        <a href="javascript:void(0);" class="slds-th__action slds-text-link--reset">
                            <span class="slds-assistive-text">Sort</span>
                            <span class="slds-truncate" title="Type">Type</span>
                            <div if:true={isTypeSort}>
                                <div if:true={isAsc}>
                                    &#9650;
                                </div>
                                <div if:true={isDsc}>
                                    &#9660;
                                </div>
                            </div>
                        </a>
                    </th>
                    <th data-id="Phone" onclick={sortPhone}>
                        <a href="javascript:void(0);" class="slds-th__action slds-text-link--reset">
                            <span class="slds-assistive-text">Sort</span>
                            <span class="slds-truncate" title="Phone">Phone</span>
                            <div if:true={isPhoneSort}>
                                <div if:true={isAsc}>
                                    &#9650;
                                </div>
                                <div if:true={isDsc}>
                                    &#9660;
                                </div>
                            </div>
                        </a>
                    </th>
                </tr>
            </thead>
            <tbody>
                <template for:each={accounts} for:item="acc">
                    <tr key={acc.Id}>
                        <td>
                            <a href={accURL} 
                               target="_blank" 
                               data-id={acc.Id} 
                               onclick={gotoAccount}>{acc.Name}</a>
                        </td>
                        <td>
                            {acc.AccountNumber}
                        </td>
                        <td>
                            {acc.Industry}
                        </td>
                        <td>
                            {acc.Type}
                        </td>
                        <td>
                            <lightning-formatted-phone value={acc.Phone}></lightning-formatted-phone>
                        </td>
                    </tr>
                </template>
            </tbody>
        </table>
    </lightning-card>
</template>

Javascript Code
import {LightningElement,wire} from 'lwc';
import accs from '@salesforce/apex/GenericController.returnAccs';

export default class CustomSorting extends LightningElement {

    accounts = [];
    accURL = "";
    isAsc = false;
    isDsc = false;
    isNameSort = false;
    isPhoneSort = false;
    isIndustrySort = false;
    isTypeSort = false;
    isAccNumSort = false;
    error;

    sortedDirection = 'asc';
    sortedColumn;

    @wire(accs)
    acc({error, data}) {
        if (data) {
            this.accounts = data;
        } else if (error) {
            this.error = error;
            console.log('error ===> ' + JSON.stringify(error));
        }
    }

    gotoAccount(event) {
        this.accURL = window.location.origin + "/" + event.currentTarget.dataset.id;
    }

    sortName(event) {
        this.isNameSort = true;
        this.isPhoneSort = false;
        this.isIndustrySort = false;
        this.isTypeSort = false;
        this.isAccNumSort = false;

        this.sortData(event.currentTarget.dataset.id);
    }

    sortAccNumber(event) {
        this.isNameSort = false;
        this.isPhoneSort = false;
        this.isIndustrySort = false;
        this.isTypeSort = false;
        this.isAccNumSort = true;

        this.sortData(event.currentTarget.dataset.id);
    }

    sortIndustry(event) {
        this.isNameSort = false;
        this.isPhoneSort = false;
        this.isIndustrySort = true;
        this.isTypeSort = false;
        this.isAccNumSort = false;

        this.sortData(event.currentTarget.dataset.id);
    }

    sortPhone(event) {
        this.isNameSort = false;
        this.isPhoneSort = true;
        this.isIndustrySort = false;
        this.isTypeSort = false;
        this.isAccNumSort = false;

        this.sortData(event.currentTarget.dataset.id);
    }

    sortType(event) {
        this.isNameSort = false;
        this.isPhoneSort = false;
        this.isIndustrySort = false;
        this.isTypeSort = true;
        this.isAccNumSort = false;

        this.sortData(event.currentTarget.dataset.id);
    }

    sortData(sortColumnName) {
        // check previous column and direction
        if (this.sortedColumn === sortColumnName) {
            this.sortedDirection = this.sortedDirection === 'asc' ? 'desc' : 'asc';
        } 
        else {
            this.sortedDirection = 'asc';
        }

        // check arrow direction
        if (this.sortedDirection === 'asc') {
            this.isAsc = true;
            this.isDsc = false;
        } 
        else {
            this.isAsc = false;
            this.isDsc = true;
        }

        // check reverse direction
        let isReverse = this.sortedDirection === 'asc' ? 1 : -1;

        this.sortedColumn = sortColumnName;

        // sort the data
        this.accounts = JSON.parse(JSON.stringify(this.accounts)).sort((a, b) => {
            a = a[sortColumnName] ? a[sortColumnName].toLowerCase() : ''; // Handle null values
            b = b[sortColumnName] ? b[sortColumnName].toLowerCase() : '';

            return a > b ? 1 * isReverse : -1 * isReverse;
        });;
    }
}

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

Output

2 comments:

  1. THIS CODE CAN'T WORK THE INTEGERS VALUES. PLEASE GIVE THE SOLUTION FOR INTEGER SORT METHOD

    ReplyDelete
  2. What if we have custom
    what should we pass in data-id for custom field
    i have passed api name of custom field like data-id ="someField__c" and it is not working
    And for standard field it is working for data-id="AnyStandardFieldApiName"

    ReplyDelete