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:
- Flexibility: The filter component must be capable of accommodating diverse attributes and data types, allowing developers to add or modify filtering criteria with ease.
- 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.
- 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.
Key Features
- 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.
- 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.
- 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.
- 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
- Clone this repository to your local machine.
- Deploy the component to your Salesforce org using Salesforce CLI or Salesforce Extension for Visual Studio Code.
- Use the component in your Lightning pages or Lightning communities.
Method 2: Single Click Installation with Unmanaged Package
- Open this link to install the package in your Sandbox OR
- Open this link to install the package in your Test Sandbox
- 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)
- 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.
<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
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:
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!
- Abhishek Patil (Author)
Abhishek
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.
What will be there in the getcontact method. I believe you forgot to mention.
Hello Rishabh,
getContact is just an example. You can write a query in Apex to return the contact data.
Also, this filter is not just limited to the Contact example, it can be any object.
Hope this helps.
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
One issue that I can already see is the “Account Name Field”. As of now, the standard data table does not support column fields like { label: ‘Account Name’, fieldName: ‘
Account.Name’, type: ‘text’ }or so… It should not be the property of an object.
Instead, do something like this in js:
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: ‘AccName’, 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: AccName}
];
@wire(fetchData)
wireOpportunity({data, error}){
if(data){
this.data.forEach(opp =>{
opp.AccName = opp.Account.Name;
} )
this.opportunity = data;
}
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
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 fromdynamicFilter.js
file, and moveitem.type
of Date to another condition to perform your desired comparision.Hope this helps.
Thanks
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;
}
Can you please help me with the error you’re getting?
Hi Abhishek,
It doesn’t display any error, but when I filter on a given date, it returns an empty table (no results).
I’ll reach out to you via email for further discussion.