Dynamic Datatable Filter

Introducing Reusable Dynamic Datatable filter in LWC

Are you in search of Reusable Dynamic Datatable filter in LWC? Then you are at right place. In today’s applications, datatables serve as essential components for displaying lists of information, such as contacts or accounts. However, relying solely on Salesforce’s standard list views might not suffice for all scenarios. There are instances where we require more flexibility in how data is presented, especially when integrating with custom components or designing complex applications with multiple AWS components.

The standard datatable functionality in Salesforce lacks built-in datatable filtering capabilities, which means developers often need to create custom filtering solutions for each instance of a datatable. This process involves writing custom JavaScript logic tailored to the specific attributes that need filtering. Moreover, reusability across different components is limited due to variations in attributes.

To address this recurring challenge, I’ve developed a reusable dynamic datatable filter in LWC. This single component simplifies the filtration process by allowing developers to configure it with just a few attributes. With this filter, developers can effortlessly integrate dynamic filtering functionalities into their applications without the need to write custom logic for each instance of a datatable.

In this article, we’ll explore the reusable dynamic datatable filter in LWC, in detail, covering its installation process, key features, and practical applications. Let’s dive into how this component can streamline datatable filtration and enhance development efficiency.

Problem Statement

The challenge at hand revolves around the need to develop a dynamic and reusable filter component that seamlessly integrates with various data tables across different applications. Traditional approaches often involve creating custom filtering solutions tailored to specific data table instances, resulting in repetitive coding efforts and limited reusability.

Key requirements for addressing this challenge include:

  1. Flexibility: The filter component must be capable of accommodating diverse attributes and data types, allowing developers to add or modify filtering criteria with ease.
  2. Reusability: It should be possible to reuse the filter component across different applications and data tables without significant modifications, thereby reducing development time and effort.
  3. Dynamism: The filter component should dynamically adapt to changes in data and user input, providing real-time filtering capabilities without requiring manual intervention.

By devising a solution that meets these requirements, developers can streamline the process of implementing dynamic filtering functionalities, enhance application scalability, and improve development efficiency.

Dynamic Data table filter in LWC

Key Features

  1. Reusability: The filter component is designed to be highly reusable, allowing developers to effortlessly integrate it with any datatable by simply populating a single line of code. This versatility enables efficient filtering across various applications and data sets without the need for extensive customization.
  2. Dynamism: With its dynamic filtering capabilities, the component adapts seamlessly to changes in filtering criteria and user input. Developers can specify the filter attribute names corresponding to the datatable columns, empowering users to filter data dynamically based on specific criteria without manual intervention.
  3. Support for Multiple Input Fields: The filter component offers extensive support for a variety of input fields, including text, number, picklist, date, datetime, and time fields. This flexibility enables developers to cater to diverse filtering requirements across different data sets and applications, enhancing user experience and data accessibility.
  4. Client-Side Processing: Leveraging client-side processing capabilities, the filter component delivers lightning-fast performance by filtering data directly within the user’s browser. This efficient processing ensures swift response times, enabling users to interact with filtered data in real-time without experiencing delays or latency issues.

These key features collectively contribute to the effectiveness and versatility of the reusable filter component, empowering developers to streamline data filtering processes, enhance application scalability, and deliver optimal user experiences across various use cases.

Installation of Dynamic Datatable filter in LWC

There are two ways by which you can use this Dynamic Datatable filter in LWC within your org, you can simply clone the repository and deploy the component in your org, or you can directly install the package to install this component.

Method 1: Installation with SFDX CLI

  1. Clone this repository to your local machine.
  2. Deploy the component to your Salesforce org using Salesforce CLI or Salesforce Extension for Visual Studio Code.
  3. Use the component in your Lightning pages or Lightning communities.

Method 2: Single Click Installation with Unmanaged Package

  1. Open this link to install the package in your Sandbox OR
  2. Open this link to install the package in your Test Sandbox
  3. It will open your recent org or ask for login. (Check the org you logged in with in case you’ve multiple orgs/sandboxes open)
  4. Click on Install for all users.

Example

Below is the example usage of the dynamic datatable filter in LWC. This demonstrates a list of contacts from the org in datatable.

parentComponent.html
<template>
    <lightning-card>
        <template if:true={contacts}>
            <c-dynamic-filter filters={filters} tdata={contacts} onfilter={handleFilter}></c-dynamic-filter>
            <br>
            <lightning-datatable
                key-field="Id"
                data={contacts}
                columns={columns}
            >
           </lightning-datatable>
        </template>
    </lightning-card>
</template>

As shown in above example, you just need to include the component reference, as shown in line 4. The attributes passed here are filters, then data passed to datatable and then event handler method, that we will call once filter is applied.

Now, lets see the JavaScript to fetch the data from Server Side

ParentComponent.js
import { LightningElement, wire } from 'lwc';
import NAME_FIELD from '@salesforce/schema/Contact.FirstName';
import LASTNAME_FIELD from '@salesforce/schema/Contact.LastName';
import EMAIL_FIELD from '@salesforce/schema/Contact.Email';
import LS_FIELD from '@salesforce/schema/Contact.LeadSource';
import EMAILOPT_FIELD from '@salesforce/schema/Contact.HasOptedOutOfEmail';
import getContacts from '@salesforce/apex/ContactController.getContacts';

const COLUMNS = [
    { label: 'First Name', fieldName: NAME_FIELD.fieldApiName, type: 'text' },
    { label: 'Last Name', fieldName: LASTNAME_FIELD.fieldApiName, type: 'text' },
    { label: 'Email', fieldName: EMAIL_FIELD.fieldApiName, type: 'text' },
    { label: 'Lead Source', fieldName: LS_FIELD.fieldApiName, type: 'text' },
    { label: 'Email Preference', fieldName: EMAILOPT_FIELD.fieldApiName, type: 'checkbox' }
];
export default class ContactList extends LightningElement {
    columns = COLUMNS;
    contacts;
    filters = [
        { label: 'Name', type: 'text', api: NAME_FIELD.fieldApiName},
        { label: 'Last Name', type: 'text', api: LASTNAME_FIELD.fieldApiName},
        { label: 'Email', type: 'text', api: EMAIL_FIELD.fieldApiName},
        { label: 'Lead Source', type: 'picklist', api: LS_FIELD.fieldApiName},
        { label: 'Email Preference', type: 'picklist', api: EMAILOPT_FIELD.fieldApiName}
    ];
    
    @wire(getContacts)
    wireContacts({data, error}){
        if(data){
            this.contacts = data; 
        }
    };

    handleFilter(event){
        this.contacts = event.detail.data;
    }
}

In above script, first highlighted block shows the Array of object that you should pass to the filter. These are nothing but your filter attributes. The sequence you define here will appear on UI as well. The mentioned three attributes are required for filter to work.

Second highlighted block receives data through event from filter component and assign it to your datatable variable. This is also a required block for filter to work.

After installation, it will look like this:

Dynamic Datatable Filter Example
Dynamic Datatable Filter Example

Customization

This reusable filter comes with no stylings and transparent background. This is made on purpose, so that you can place this component anywhere and match the stylings of detitanation. As shown in above example, we can see, the reusable filter is placed inside the card, so that background will match the filter.

Apart from that, you can add styling to filter inputs by modifying the core input component.

Changelog

Release 1.1

  • Optimized the core code
  • Minor Bug Fixes

Release 1.0

  • Initial Release

Contributions:

Liked this Dynamic Datatable filter in LWC, and want to update it further? Feel free to raise a PR to this GitHub branch, your changes will be reviewed and you will be the part of this list!

Oh hi there!
It’s nice to meet you.

Sign up to receive awesome content in your inbox, every month.

We don’t spam! Read our privacy policy for more info.

Abhishek Patil
Abhishek
Managing Director - Salesforce Practice (India) at Valuehub

Mr. Abhishek, an experienced Salesforce Technical Lead with over 4+ years of development experience and 8x Salesforce Certified. His expertise is in Salesforce Development, including Lightning Web Components, Apex Programming, and Flow has led him to create his blog, SFDC Hub.

Subscribe
Notify of
guest
10 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Rishabh
Rishabh
7 months ago

What will be there in the getcontact method. I believe you forgot to mention.

Rishabh
Rishabh
Reply to  Abhishek
7 months ago

I am trying to use this for opportunity object like this

public class getOpportunity {
    @AuraEnabled(cacheable=true)
    public static List<Opportunity> fetchData() {

        return [SELECT Id, Name, Description, CloseDate, Amount, NextStep, Account.Name FROM Opportunity];
    }
}

HTML

<template>
    <lightning-card>
        <template if:true={opportunity}>
            <c-dynamic-filter filters={filters} tdata={opportunity} onfilter={handleFilter}></c-dynamic-filter>
            <br>
            <lightning-datatable
                key-field=“Id”
                data={opportunity}
                columns={columns}
            >
           </lightning-datatable>
        </template>
    </lightning-card>
</template>

JS —

import { LightningElement, wire } from ‘lwc’;
import NAME_FIELD from ‘@salesforce/schema/Opportunity.Name’;
import DESCRIPTION_FIELD from ‘@salesforce/schema/Opportunity.Description’;
import CLOSEDATE_FIELD from ‘@salesforce/schema/Opportunity.CloseDate’;
import AMOUNT_FIELD from ‘@salesforce/schema/Opportunity.Amount’;
import NEXTSTEP_FIELD from ‘@salesforce/schema/Opportunity.NextStep’;
import ACCOUNTNAME_FIELD from ‘@salesforce/schema/Opportunity.Account.Name’;
import fetchData from ‘@salesforce/apex/getOpportunity.fetchData’;

const COLUMNS = [
    { label: ‘Opportunity Name’, fieldName: ‘Name’, type: ‘text’ },
    { label: ‘Opportunity Description’, fieldName: ‘Description’, type: ‘text’ },
    { label: ‘Close Date’, fieldName: ‘CloseDate’, type: ‘date’ },
    { label: ‘Amount’, fieldName: ‘Amount’, type: ‘currency’ },
    { label: ‘Next Steps’, fieldName: ‘NextStep’, type: ‘text’ },
    { label: ‘Account Name’, fieldName: ‘Account.Name’, type: ‘text’ }
];
export default class OpportunityList extends LightningElement {
    columns = COLUMNS;
    opportunity;
    filters = [
        { label: ‘Name’, type: ‘text’, api: NAME_FIELD.fieldApiName},
        { label: ‘Description’, type: ‘text’, api: DESCRIPTION_FIELD.fieldApiName},
        { label: ‘Close Date’, type: ‘date’, api: CLOSEDATE_FIELD.fieldApiName},
        { label: ‘Amount’, type: ‘currency’, api: AMOUNT_FIELD.fieldApiName},
        { label: ‘Next Step’, type: ‘text’, api: NEXTSTEP_FIELD.fieldApiName},
        { label: ‘Account Name’, type: ‘text’, api: ACCOUNTNAME_FIELD.fieldApiName}
    ];
   
    @wire(fetchData)
    wireOpportunity({data, error}){
        if(data){
            this.opportunity = data;
        }
    };

    handleFilter(event){
        this.opportunity = event.detail.data;
    }
}

I have added the dynamicFilter component but it is throwing an error

error-lwc
Mathilde
Mathilde
5 months ago

Hello,
The piece of code is awesome! For text and picklist it is working perfectly, however I tried the date option and it was not returning any results. Also, is there a way to put a date in the filter value and return all results for which the date column data is >= date filter value?
Thank you and best,
Mathilde

Abhishek Patil
Abhishek
Admin
Reply to  Mathilde
5 months ago

Hello,

Thanks for checking it out. I’ll check the issue with date fields.
However, even you can add your custom conditions for date. Just checkout filterData method from dynamicFilter.js file, and move item.type of Date to another condition to perform your desired comparision.

Hope this helps.

Thanks

Mathilde
Mathilde
Reply to  Abhishek
5 months ago

Hi Abhishek,
Yes, I tried modifying it but it doesn’t work (I am new to LWC).
Even just trying to get the filtered value for a given date is not working 🙁

else if (item.type == ‘date’){
let filterdate = new Date(item[filter.api]).toISOString();
let filtervalue = new Date(filter.value).toISOString();
return filterdate == filtervalue;
}

Abhishek Patil
Abhishek
Admin
Reply to  Mathilde
5 months ago

Can you please help me with the error you’re getting?

Mathilde
Mathilde
Reply to  Abhishek
5 months ago

Hi Abhishek,
It doesn’t display any error, but when I filter on a given date, it returns an empty table (no results).

Abhishek Patil
Abhishek
Admin
Reply to  Mathilde
5 months ago

I’ll reach out to you via email for further discussion.

Shopping Cart
10
0
Would love your thoughts, please comment.x
()
x