Dynamic Filters for Salesforce LWC Lightning Datatable

In the Salesforce LWC lightning data table, we can sort and filter records with multiple conditions in a single list view by applying dynamic filters. In this Salesforce tutorial, we will learn how to add dynamic filters to an LWC Lightning data table in Salesforce.

Dynamic Filters in LWC Data Table

In LWC data tables, adding dynamic filters means applying different filters, like dropdowns or picklists, to specific columns in a Lightning data table to filter the data. We can use components like lightning-combobox or lightning-input for filter options and JavaScript logic to filter the table’s data based on the selected filter.

With this feature, we can apply multiple filters to get the records in the data table based on the different values selected in the filters.

Add Dynamic Filters to LWC Lightning Data Table

In LWC data tables, we apply filters for various criteria based on the different field values, which can be a picklist, text, currency, or boolean field. In the steps below, we will see how to apply dynamic filters for multiple fields to the Salesforce LWC data tables.

When we have to apply multiple filters for different fields, such as filtering opportunity records when the amount (currency) is a minimum of 40000 and the stage is closed won.

This contains more than one filter with different data types, so when we apply filters based on multiple values, it might be text, currency, or picklist.

For the different data type filters, we can add multiple input fields that combine all filter criteria and give the results.

In this example, I will create a LWC lightning data table with field columns of different data types, such as Name(text), Amount ( currency), Stage, and Type (picklist), then a date field (Close date).

  1. Create a controller class to fetch the Opportunity record fields with different data types.
public with sharing class OpportunityController {
    @AuraEnabled(cacheable=true)
    public static List<Opportunity> getOpportunities() {
        return [SELECT Id, Name, StageName, Type, Amount, CloseDate 
                FROM Opportunity 
                WHERE IsDeleted = false 
                LIMIT 100];
    }
}
  1. To get the picklist field values of the Stage and Type field from the opportunity object, add the code below in the controller class.
        List<String> conditions = new List<String>();
        
        }
        if (amountFilter != null) {
            conditions.add('Amount >= :amountFilter');
        }
        if (String.isNotBlank(stageFilter)) {
            conditions.add('StageName = :stageFilter');
        }
        if (String.isNotBlank(typeFilter)) {
            conditions.add('Type = :typeFilter');
        }
        if (closeDateFilter != null) {
            conditions.add('CloseDate = :closeDateFilter');
        }
        
        if (!conditions.isEmpty()) {
            query += ' AND ' + String.join(conditions, ' AND ');
        }
        
        query += ' LIMIT 100';
        
        return Database.query(query);
    }
    
    @AuraEnabled(cacheable=true)
    public static List<String> getStagePicklistValues() {
        List<String> picklistValues = new List<String>();
        Schema.DescribeFieldResult fieldResult = Opportunity.StageName.getDescribe();
        List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();
        for (Schema.PicklistEntry f : ple) {
            picklistValues.add(f.getLabel());
        }
        return picklistValues;
    }
    
    @AuraEnabled(cacheable=true)
    public static List<String> getTypePicklistValues() {
        List<String> picklistValues = new List<String>();
        Schema.DescribeFieldResult fieldResult = Opportunity.Type.getDescribe();
        List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();
        for (Schema.PicklistEntry f : ple) {
            picklistValues.add(f.getLabel());
        }
        return picklistValues;
    }
}

In the above apex class, we have defined logic to consider the filter even if one filter is applied, and applying multiple filters will combine them using the AND operator.

To fetch picklist field values, we have created lists getTypePicklistValues() and getStagePicklistValues().

  1. After this, create the LWC component and enter the code in the JS file. In this code, we have handled the logic of fetching the opportunities fields.
import { LightningElement, wire } from 'lwc';
import getOpportunities from '@salesforce/apex/OpportunityController.getOpportunities';
import getStagePicklistValues from '@salesforce/apex/OpportunityController.getStagePicklistValues';
import getTypePicklistValues from '@salesforce/apex/OpportunityController.getTypePicklistValues';

const columns = [
    { label: 'Opportunity Name', fieldName: 'Name', type: 'text' },
    { label: 'Amount', fieldName: 'Amount', type: 'currency' },
    { label: 'Stage', fieldName: 'StageName', type: 'text' },
    { label: 'Type', fieldName: 'Type', type: 'text' },
    { label: 'Close Date', fieldName: 'CloseDate', type: 'date' }
];

export default class OpportunityDataTable extends LightningElement {
    opportunities = [];
    columns = columns;
    nameFilter = '';
    amountFilter = '';
    stageFilter = '';
    typeFilter = '';
    closeDateFilter = '';
    stageOptions = [];
    typeOptions = [];
    error;

    @wire(getStagePicklistValues)
    wiredStages({ error, data }) {
        if (data) this.stageOptions = data.map(value => ({ label: value, value: value }));
        else if (error) this.error = error;
    }

    @wire(getTypePicklistValues)
    wiredTypes({ error, data }) {
        if (data) this.typeOptions = data.map(value => ({ label: value, value: value }));
        else if (error) this.error = error;
    }

    handleInputChange(event) {
        this[event.target.name] = event.target.value;
        this.fetchOpportunities();
    }

    handleClearFilters() {
        this.nameFilter = this.amountFilter = this.stageFilter = this.typeFilter = this.closeDateFilter = '';
        this.template.querySelectorAll('lightning-input, lightning-combobox')
            .forEach(input => input.value = '');
        this.fetchOpportunities();
    }

    fetchOpportunities() {
        getOpportunities({
            nameFilter: this.nameFilter,
            amountFilter: this.amountFilter ? parseFloat(this.amountFilter) : null,
            stageFilter: this.stageFilter,
            typeFilter: this.typeFilter,
            closeDateFilter: this.closeDateFilter || null
        })
        .then(result => {
            this.opportunities = result;
            this.error = undefined;
        })
        .catch(error => {
            this.error = error;
            this.opportunities = [];
        });
    }

    connectedCallback() {
        this.fetchOpportunities();
    }
}

The above code defines the table columns and manages filter inputs for name, amount, stage, type, and close date.

The @wire decorators fetch picklist values for stage and type from the Apex class. Then, handleInputChange updates filters and refreshes data, handleClearFilters resets all filters, and fetchOpportunities calls the Apex method to fetch filtered Opportunity records.

  1. Enter the code below in the HTML file, which includes input fields for filtering by name, amount, stage, type, and close date, using lightning-input and lightning-combobox components.
<template>
    <lightning-card title="Opportunity Data Table">
        <div class="slds-m-around_medium">
            <div class="slds-grid slds-gutters">
                <div class="slds-col">
                    <lightning-input 
                        type="text" 
                        name="nameFilter" 
                        label="Name" 
                        value={nameFilter} 
                        onchange={handleInputChange}
                    ></lightning-input>
                </div>
                <div class="slds-col">
                    <lightning-input 
                        type="number" 
                        name="amountFilter" 
                        label="Minimum Amount" 
                        value={amountFilter} 
                        onchange={handleInputChange}
                    ></lightning-input>
                </div>
                <div class="slds-col">
                    <lightning-combobox
                        name="stageFilter"
                        label="Stage"
                        value={stageFilter}
                        options={stageOptions}
                        onchange={handleInputChange}
                    ></lightning-combobox>
                </div>
                <div class="slds-col">
                    <lightning-combobox
                        name="typeFilter"
                        label="Type"
                        value={typeFilter}
                        options={typeOptions}
                        onchange={handleInputChange}
                    ></lightning-combobox>
                </div>
                <div class="slds-col">
                    <lightning-input 
                        type="date" 
                        name="closeDateFilter" 
                        label="Close Date" 
                        value={closeDateFilter} 
                        onchange={handleInputChange}
                    ></lightning-input>
                </div>
            </div>

            <div class="slds-m-top_medium">
                <lightning-button 
                    label="Clear Filters" 
                    variant="neutral" 
                    onclick={handleClearFilters}
                ></lightning-button>
            </div>

            <template if:true={opportunities}>
                <lightning-datatable
                    key-field="Id"
                    data={opportunities}
                    columns={columns}
                    hide-checkbox-column="true"
                ></lightning-datatable>
            </template>
        </div>
    </lightning-card>
</template>

The “Clear Filters” button resets the form. If an error occurs, an error message is displayed; otherwise, a data table with the filtered Opportunity data is displayed.

  1. At last, enter the code below in the meta.xml file to make the component visible to the Lightning pages.
<isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
  1. After this, deploy the LWC component to the Lightning page to view the data table.

On the lightning page, you will see the different filters, and we can select multiple filters. The more filters we apply, the more specific search results we will get in the data table.

Filter with amount, stage, and type:

Add multiple filter conditions in salesforce LWC table

Filter with name and stage:

LWC data table with dynamic filters

Filter with close date:

Dynamic filters in LWC data table

This way, we can add multiple dynamic filters for column fields with different data types in the Salesforce LWC data table.

Conclusion

In this Salesforce tutorial, we have learned how to add dynamic filters in the LWC data table. In the above example, we implemented multi-field filters for text, currency, picklist, and date fields.

By following the above example, you can add a dynamic filter by adding multiple filter input fields with different data types.

You may also like to read:

Agentforce in Salesforce

DOWNLOAD FREE AGENTFORCE EBOOK

Start with AgentForce in Salesforce. Create your first agent and deploy to your Salesforce Org.

Salesforce flows complete guide

FREE SALESFORCE FLOW EBOOK

Learn how to work with flows in Salesforce with 5 different real time examples.