Real Time Custom Dependent Picklist From Record Field Values in LWC

You might have seen various post on fetching dependent picklist values defined on fields in Lightning Web Component. Did you ever came across requirement to generate real time custom dependent picklist values from existing record field values? To understand the use case, focus on images below:-

There are three records on account object where Type, Rating and Industry field have some value. Our aim is to build a custom picklist within Lightning Web Component based on these field values. To understand the real time custom dependent picklist values from existing record field values within Lightning Web Component, check below image:-

This blog shows you generating real time custom dependent picklist field in Lightning Web Component on Account Object. You can do the same in similar manner on any object by taking any three fields in it.

Also, Make sure you are not dealing with bulk records. The governor limit applies here. The group by query should not exceed 50000 records. In other words, The total unique combination of those three fields unique value should not be greater than 50000, else it will hit the governor limit and component will throw an error.

Generally, working with picklist field will save you from hitting the limit. In case of text type field, you might hit the limit as text field can have many unique values.

REAL TIME CUSTOM DEPENDENT PICKLIST – USE CASE

A solid use case of this component can be building a search component where you are providing users with existing values on fields in more decorated manner. There can be more use cases like this. You can try to explore them.

REAL TIME CUSTOM DEPENDENT PICKLIST IN LWC- CODE

We need a Lightning Web Component with an Apex controller to achieve this functionality. They are:-

  • customDependentPicklist – Lightning Web Component
  • DependentPicklistGenerator – Apex Class

DependentPicklistGenerator

The apex class has fetchDependentPicklistValues method which returns the picklist values of the all the three fields to the Lightning Web Component as a JSON string.

public with sharing class DependentPicklistGenerator {
    @AuraEnabled(cacheable=true)
    public static String fetchDependentPicklistValues(){
        Map<String,List<Map<String,List<String>>>> MapOfDependentPicklsit = new Map<String,List<Map<String,List<String>>>>();
        for(AggregateResult ag : [select Type, Rating, Industry from Account where Type!=null and Rating!=null and Industry!=null Group By Type, Rating, Industry]){
            Map<String,List<String>> mapOfRatingAndIndustry = new Map<String,List<String>>();
            if(mapOfRatingAndIndustry.containsKey(String.valueOf(ag.get('Rating')))){
                mapOfRatingAndIndustry.get(String.valueOf(ag.get('Rating'))).add(String.valueOf(ag.get('Industry')));
            }else{
                mapOfRatingAndIndustry.put(String.valueOf(ag.get('Rating')),new List<String>{String.valueOf(ag.get('Industry'))});
            }
            if(MapOfDependentPicklsit.containsKey(String.valueOf(ag.get('Type')))){
                MapOfDependentPicklsit.get(String.valueOf(ag.get('Type'))).add(mapOfRatingAndIndustry);
            }else{
                MapOfDependentPicklsit.put(String.valueOf(ag.get('Type')),new List<Map<String,List<String>>>{mapOfRatingAndIndustry});
            }
        }
        return JSON.serialize(MapOfDependentPicklsit);
    }
}

customDependentPicklist.html

The html file of the Lightning Web Component uses lightning-combobox for showing picklist field.

<template>
    <lightning-card title="Real Time Custom Dependent Picklist From Record Field Values" icon-name="custom:custom63">
        <lightning-layout multiple-rows>
            <lightning-layout-item size="12" small-device-size="6" medium-device-size="4" large-device-size="3"
                padding="around-small">
                <lightning-combobox name="Type" label="Type" placeholder="Select Type" options={typeOptions}
                    onchange={handleTypeChange} value={selectedTypeValue}></lightning-combobox>
            </lightning-layout-item>
            <lightning-layout-item size="12" small-device-size="6" medium-device-size="4" large-device-size="3"
                padding="around-small">
                <lightning-combobox name="Rating" label="Rating" placeholder="Select Rating" options={ratingOptions}
                    onchange={handleRatingChange} value={selectedRatingValue}></lightning-combobox>
            </lightning-layout-item>
            <lightning-layout-item size="12" small-device-size="6" medium-device-size="4" large-device-size="3"
                padding="around-small">
                <lightning-combobox name="Industry" label="Industry" placeholder="Select Industry"
                    options={industryOptions} onchange={handleIndustryChange} value={selectedIndustryValue}>
                </lightning-combobox>
            </lightning-layout-item>
        </lightning-layout>
    </lightning-card>
</template>

customDependentPicklist.js

The js file of the Lightning Web Component uses wired service to make apex method call on the load of the page and then parse the JSON string to object and create option values of the picklist field. The combobox change handler further create option values for dependent picklist fields.

import { LightningElement, wire, track } from 'lwc';
import fetchDependentPicklistValues from '@salesforce/apex/DependentPicklistGenerator.fetchDependentPicklistValues';
export default class CustomDependentPicklist extends LightningElement {
    @track typeDependentPicklistWrapperArray;
    @track typeOptions;
    @track ratingOptions;
    @track industryOptions;
    selectedTypeValue;
    selectedRatingValue;
    selectedIndustryValue;
    @wire(fetchDependentPicklistValues, {})
    wiredFetchDependentPicklistValues({ error, data }) {
        if (data) {
            try {
                this.typeDependentPicklistWrapperArray = JSON.parse(data);
                let options = [];
                for (var key in JSON.parse(data)) {
                    options.push({ label: key, value: key });
                }
                this.typeOptions = options;
                this.ratingOptions = undefined;
                this.industryOptions = undefined;
            } catch (error) {
                console.error('check error here', error);
            }
        } else if (error) {
            console.error('check error here', error);
        }
    }

    handleTypeChange(event) {
        try {
            this.selectedRatingValue = undefined;
            this.selectedIndustryValue = undefined;
            this.ratingOptions = undefined;
            this.industryOptions = undefined;
            let options = [];
            this.selectedTypeValue = event.detail.value;
            if (this.typeDependentPicklistWrapperArray) {
                for (var key in this.typeDependentPicklistWrapperArray) {
                    if (this.selectedTypeValue === key) {
                        for (var subkey in this.typeDependentPicklistWrapperArray[key]) {
                            for (var childkey in this.typeDependentPicklistWrapperArray[key][subkey]) {
                                options.push({ label: childkey, value: childkey });
                            }
                        }
                        break;
                    }
                }
                options = options.filter((thing, index) => {
                    const _thing = JSON.stringify(thing);
                    return index === options.findIndex(obj => {
                        return JSON.stringify(obj) === _thing;
                    });
                });
                this.ratingOptions = options;
            }
        } catch (error) {
            console.error('check error here', error);
        }

    }

    handleRatingChange(event) {
        try {
            this.selectedIndustryValue = undefined;
            this.industryOptions = undefined;
            let options = [];
            this.selectedRatingValue = event.detail.value;
            if (this.typeDependentPicklistWrapperArray) {
                for (var key in this.typeDependentPicklistWrapperArray) {
                    if (this.selectedTypeValue === key) {
                        for (var subkey in this.typeDependentPicklistWrapperArray[key]) {
                            for (var childkey in this.typeDependentPicklistWrapperArray[key][subkey]) {
                                if (this.selectedRatingValue === childkey) {
                                    for (var grandchildkey in this.typeDependentPicklistWrapperArray[key][subkey][childkey]) {
                                        options.push({ label: this.typeDependentPicklistWrapperArray[key][subkey][childkey][grandchildkey], value: this.typeDependentPicklistWrapperArray[key][subkey][childkey][grandchildkey] });
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
                options = options.filter((thing, index) => {
                    const _thing = JSON.stringify(thing);
                    return index === options.findIndex(obj => {
                        return JSON.stringify(obj) === _thing;
                    });
                });
                this.industryOptions = options;
            }
        } catch (error) {
            console.error('check error here', error);
        }

    }

    handleIndustryChange(event) {
        this.selectedIndustryValue = event.detail.value;
    }
}

customDependentPicklist.js-meta.xml

The xml file of the Lightning Web Component enables component to be used with Lightning pages in Lightning Experience.

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>51.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Demo

It’s time to look what we have just build. You need to add the component on the Home or record or App page to test it.

Check out more here : – Lightning Web Component Examples

Leave a Reply