1

What I have implemented: I have a lightning-datatable and the results can be filtered with three lightning-combobox components working together. The options for these comboboxes are fed from separate picklist fields of a custom object. I've implemented the below custom filter functionality on these comboboxes to narrow down the results of the datatable:

HTML for first Combobox

<lightning-layout-item padding="around-small">
    <div class="slds-clearfix">
        <div class="slds-float_right">
            <template if:true={firstPickListValues.data} >
                <lightning-combobox name="first" label="First" value={firstPLValue} placeholder="Select"
                        options={firstPickListOptions} onchange={handleFirstPLChange}></lightning-combobox>
            </template>
        </div>
    </div>
</lightning-layout-item>

JS for filter logic on the first Combobox:

import { getPicklistValues, getObjectInfo} from 'lightning/uiObjectInfoApi';
import CUSTOM_OBJECT from '@salesforce/schema/Hotels__c';
import CATEGORY_FIELD from '@salesforce/schema/Hotels__c.Category__c';

custObjectInfo;
@track firstOptionItems = [];
@track firstPLValue = 'All';
@track secondPLValue = 'All';
@track thirdPLValue = 'All';

@wire(getObjectInfo, { objectApiName: CUSTOM_OBJECT })
custObjectInfo;

@wire(getPicklistValues, {
    recordTypeId: "$custObjectInfo.data.defaultRecordTypeId",
    fieldApiName: CATEGORY_FIELD
})
firstPickListValues;

//Pushing 'All' as first value on the retrived picklist options.
addAllAsFirstOption(){
    this.firstOptionItems = [...this.firstPickListValues.data.values];
    var allPickListVal = {"attributes":null,"label":"All","validFor":[],"value":"All"};
    this.firstOptionItems.unshift(allPickListVal);
}

//Combobox options
get firstPickListOptions() {
    this.addAllAsFirstOption();
    return this.firstOptionItems;
}

//onchange event
handleFirstPLChange( event ) {
    this.firstPLValue = event.detail.value;
    this.firstPLCheck(this.records);
}


firstPLCheck  = (PickListData) => {
    this.data = [];
    //Scenario: Second != 'All' and Third != 'All'
    if((this.secondPLValue !== 'All' && this.thirdPLValue !== 'All')){
        PickListData.forEach(element => {
            if(this.secondPLValue === element.Second && this.thirdPLValue === element.Third){
                if(this.firstPLValue === 'All'){
                    this.data.push(element);  
                }
                else if(this.firstPLValue === element.First){
                    this.data.push(element);   
                }
            } 
        });
    //Scenario: Second == 'All' and Third != 'All'
    } else if((this.secondPLValue === 'All' && this.thirdPLValue !== 'All')){
        PickListData.forEach(element => {
            if( this.thirdPLValue === element.Third){
                if(this.firstPLValue === 'All'){
                    this.data.push(element);  
                }
                else if(this.firstPLValue === element.First){
                    this.data.push(element);   
                }
            } 
        });
    //Scenario: Second != 'All' and Third == 'All'
    } else if((this.secondPLValue !== 'All' && this.thirdPLValue === 'All')){
        PickListData.forEach(element => {
            if( this.secondPLValue === element.Second){
                if(this.firstPLValue === 'All'){
                    this.data.push(element);  
                }
                else if(this.firstPLValue === element.First){
                    this.data.push(element);   
                }
            } 
        });
    //Scenario: Second == 'All' and Third == 'All'
    } else{
        PickListData.forEach(element => {
            if(this.firstPLValue === 'All'){
                this.data.push(element);  
            }
            else if(this.firstPLValue === element.First){
                this.data.push(element);   
            }
        });
    } 
}

I am repeating the same logic for other two comboboxes by replacing respective ----PLValue property. As I can see, the filters are working great and it satisfied our requirement.

Question: Is there a way we can optimize the code by dynamically using the same onchange event on all the three comboboxes where we call the same ----PLCheck function and get all filters working as intended? With my current implementation, I feel like I am just copy/pasting the same code three times to achieve the entire filter logic working.

1 Answer 1

4

Array.filter is your friend here:

this.data = this.records.filter(
    record => (this.firstPLValue === 'All' || record.First === this.firstPLValue)
).filter(
    record => (this.secondPLValue === 'All' || record.Second === this.secondPLValue)
).filter(
    record => (this.thirdPLValue === 'All' || record.Third === this.thirdPLValue)
);

Using this logic, the array is filtered three times, the end result being the list of records that satisfy all the requirements.

No if statements, no push calls. Note that this also is efficient in the terms that if the first picklist value filters out some records, they don't need to be checked for the second and third passes (ditto for the second pass as well).

5
  • I didn't get the part where you mentioned: "if the first picklist value filters out some records, they don't need to be checked for the second and third passes". In my thought process: If FirstValue == USA, I would need to check if State == 'All' or 'California', and City = 'All' or 'San Fransisco'. And based on the 2nd/3rd values, my results should narrow down. Are you saying, this scenario gets covered too? Just confused.
    – SatyaV
    Aug 19, 2021 at 18:44
  • 1
    @ArnoldJr. Correct. Each record has to pass the first filter to get to the next. If you've ever seen multi-stage water filters that get progressively finer, it's the same thought here. We take out as many invalid values as possible as early as possible to reduce future computations.
    – sfdcfox
    Aug 19, 2021 at 18:49
  • Sounds great to me. Let me try this approach and get back to you in some time.
    – SatyaV
    Aug 19, 2021 at 18:52
  • How do you know this logic? For real, I wanted to know/learn how you come up to this solution. It worked like a charm. Is that because of all the exposure you get from answering or by mere experience? Or, you dedicate some time reading/understanding concepts more than your job asks? Amazing person Alive!!
    – SatyaV
    Aug 19, 2021 at 19:24
  • 1
    @ArnoldJr. Thanks! I have at least 34 years of programming experience in dozens of programming languages. I've studied a lot of algorithms, read a lot of books, worked on many challenging projects, suffered many failures over the decades, and participated in thousands of hours of helping people both here on SFSE and other networks. I'm also naturally gifted in computer science in general, able to "see" algorithms in my head before I even write a line of code. I certainly have limits, though, but I always try to challenge them.
    – sfdcfox
    Aug 19, 2021 at 19:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .