Custom Table with filtering and Sorting using LWC (Lightning Web Component)

Sample Code:
Apex Class:

public with sharing class AccountController {
 
    @AuraEnabled( cacheable = true )
    public static List< Account > fetchAccounts() {
     
        return [
            SELECT Id, Name, Industry, Rating, Type, AccountNumber, Phone, Active__c, SLA__c
            FROM Account
            LIMIT 10
        ];
         
    }
     
}

 
HTML:

<template>
    <div class="slds-box slds-theme--default">
        <div class="slds-text-color_inverse slds-text-heading_large" style="padding:0.5rem;background:#16325c">        
            Accounts
        </div>
        <div class="slds-float_right">        
            <lightning-input type="search" onblur={handleKeyChange} class="slds-m-bottom_small" label="Search" maxlength="70">  
            </lightning-input>  
        </div>
        <table class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_striped">
                <thead>
                <tr class="slds-line-height_reset">
                    <th class="" scope="col">
                        <a class="slds-th__action slds-text-link_reset" href="javascript:void(0);" role="button" tabindex="0" onclick={sortRecs} name="Name">
                            Account Name
                        </a>
                    </th>
                    <th class="" scope="col">
                        <a class="slds-th__action slds-text-link_reset" href="javascript:void(0);" role="button" tabindex="0" onclick={sortRecs} name="AccountNumber">
                            Account Number
                        </a>
                    </th>
                    <th class="" scope="col">
                        <a class="slds-th__action slds-text-link_reset" href="javascript:void(0);" role="button" tabindex="0" onclick={sortRecs} name="Industry">
                            Industry
                        </a>
                    </th>
                    <th class="" scope="col">
                        <a class="slds-th__action slds-text-link_reset" href="javascript:void(0);" role="button" tabindex="0" onclick={sortRecs} name="Rating">
                            Rating
                        </a>
                    </th>
                    <th class="" scope="col">
                        <a class="slds-th__action slds-text-link_reset" href="javascript:void(0);" role="button" tabindex="0" onclick={sortRecs} name="Type">
                            Type
                        </a>
                    </th>
                    <th class="" scope="col">
                        <a class="slds-th__action slds-text-link_reset" href="javascript:void(0);" role="button" tabindex="0" onclick={sortRecs} name="Phone">
                            Phone
                        </a>
                    </th>
                    <th class="" scope="col">
                        <a class="slds-th__action slds-text-link_reset" href="javascript:void(0);" role="button" tabindex="0" onclick={sortRecs} name="Active__c">
                            Active
                        </a>
                    </th>
                    <th class="" scope="col">
                        <a class="slds-th__action slds-text-link_reset" href="javascript:void(0);" role="button" tabindex="0" onclick={sortRecs} name="SLA__c">
                            SLA
                        </a>
                    </th>
                </tr>
            </thead>
            <tbody>
                <template iterator:it={records}>
                    <tr class="slds-hint-parent" key = {it.value.Id}>
                        <td data-label="Account Name">
                            <div class="slds-cell-wrap">{it.value.Name}</div>
                        </td>
                        <td data-label="Account Number">
                            <div class="slds-cell-wrap">{it.value.AccountNumber}</div>
                        </td>
                        <td data-label="Industry">
                            <div class="slds-cell-wrap">{it.value.Industry}</div>
                        </td>
                        <td data-label="Rating">
                            <div class="slds-cell-wrap">{it.value.Rating}</div>
                        </td>
                        <td data-label="Type">
                            <div class="slds-cell-wrap">{it.value.Type}</div>
                        </td>
                        <td data-label="Phone">
                            <div class="slds-cell-wrap">{it.value.Phone}</div>
                        </td>
                        <td data-label="Active">
                            <div class="slds-cell-wrap">{it.value.Active__c}</div>
                        </td>
                        <td data-label="SLA">
                            <div class="slds-cell-wrap">{it.value.SLA__c}</div>
                        </td>
                    </tr>
                </template>
            </tbody>
        </table>
    </div>
</template>

JavaScript:
import { LightningElement, wire } from 'lwc';
import fetchAccounts from '@salesforce/apex/AccountController.fetchAccounts';

export default class Sample extends LightningElement {

    records;
    sortedColumn;
    sortedDirection = 'asc';
    initialRecords;

    @wire( fetchAccounts )  
    wiredAccount( { error, data } ) {
        if (data) {

            this.records = data;
            this.initialRecords = data;
            this.error = undefined;

        } else if ( error ) {

            this.error = error;
            this.initialRecords = undefined;
            this.records = undefined;

        }
    }  

    sortRecs( event ) {

        let colName = event.target.name;
        console.log( 'Column Name is ' + colName );
        if ( this.sortedColumn === colName ) {
            this.sortedDirection = ( this.sortedDirection === 'asc' ? 'desc' : 'asc' );
        }
        else {
            this.sortedDirection = 'asc';
        }

        let isReverse = this.sortedDirection === 'asc' ? 1 : -1;

        this.sortedColumn = colName;

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

            b = b[ colName ] ? b[ colName ].toLowerCase() : '';
            return a > b ? 1 * isReverse : -1 * isReverse;
        });;

    }

    handleKeyChange( event ) {  
          
        const searchKey = event.target.value.toLowerCase();  
        console.log( 'Search Key is ' + searchKey );
 
        if ( searchKey ) {  

            this.records = this.initialRecords;
 
             if ( this.records ) {

                let recs = [];
                for ( let rec of this.records ) {

                    console.log( 'Rec is ' + JSON.stringify( rec ) );
                    let valuesArray = Object.values( rec );
                    console.log( 'valuesArray is ' + valuesArray );
 
                    for ( let val of valuesArray ) {
                        
                        if ( val ) {

                            if ( val.toLowerCase().includes( searchKey ) ) {

                                recs.push( rec );
                                break;
                        
                            }

                        }

                    }
                    
                }

                console.log( 'Recs are ' + JSON.stringify( recs ) );
                this.records = recs;

             }
 
        }  else {

            this.records = this.initialRecords;

        }
 
    }  

}

JS-meta.xml:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>    
    <isExposed>true</isExposed>
     <targets>
        <target>lightning__Tab</target>
    </targets>
</LightningComponentBundle>
 
Output:

Sorting based on Custom Field Active__c:  
 
 
Sorting based on Standard Field Name: 
 

Filtering Data:


8 comments:

  1. what if we have costom field for sorting

    ReplyDelete
    Replies
    1. it is not working actually for me
      for standard field i have passed api name as name in html like name="Name", and this is working .
      but when i am passing custome field api name as name="someField__c" it is not working
      even i have tried just with field name like name="someField" ,but same result.
      i have consoled a and b in sortRecs()
      i am getting values for standard field like name and type
      but for custome field i am getting nothing in a and b.

      Delete
    2. what should be in name in html file for custome field to get values

      Delete
    3. I just updated the code by including custom field. Check and cross verify.

      Delete
    4. Hi Magulan Duraipandian
      Thank You so much for quick response.
      Yes it is working for custome field ,but i am still stuck.
      I think this is because of field type.
      I tested with custome field of type text and picklist it is working.
      But my issue is I want to filter Custome fields of type Checkbox and Number ,and i think for number and checkbos we need other logic.
      can you please help me to get that.

      Delete
    5. In the above example, active is a check box field only.

      Delete
    6. Ok Thank You.
      May be i am doing something wrong with my code.

      Delete