RecordId based Dynamic and Dependent Picklists in Apex and Lightning Web Components

Picklists in Apex

Did you ever come across a scenario to generate dependent picklists in Apex based on existing record field values based on current recordId on a Lightning Web Component? Sounds Quiet Interesting!

Picklists are used to display a list of selectable options. It can be a single select or multi-select picklist.

We use lightning select or Combobox components for creating picklists in apex, here we will be using Combobox.

dynamic picklists in apex

Understanding the Use Case

Hereby we have a lightning web component linked to the Account record page to create a case based on two picklist values of ‘Service Type’ and ‘Request Type’.

Functional Requirements

  1. The access to ‘Service Type’ and ‘Request Type’ picklist values are defined via Category and Speciality of the particular account record. The ‘Service Type’ is thereby a dynamic picklist based on the Account.
  2. While, the picklist values on the ‘Request Type’ are populated based on the ‘Service Type’ selection by the user and thereby are dynamic and a dependent picklist as well.
picklists in apex

For manipulating the ‘Service Type’ picklist values based on the Category and Specialty of an Account record we created another object named Access Manager. The object is meant to specify which Category and Specialty Account should have access to which ‘Service Type’ and further which all ‘Request Types’.

When we want to enable an account of a particular category and specialty to create a case of a specific Service Type and Request type, we just need to create an Access Manager record with the particulars. The ‘Service Type’ and ‘Request Type’ are here part of a global picklist and comes with their values in place.

Based on the ‘Service Type’ and ‘Request Type’ on the LWC component different layouts are thereby presented to the user. Let’s dig into it.

Apex Controller

public without sharing class CaseRequestController {

    //this method produces dynamic picklist values

	@AuraEnabled(cacheable=true)
        public static PicklistWrapper getDynamicPicklist(Id AccountId){
        PicklistWrapper objWrapper = new PicklistWrapper();
        Map<String,List<String>> MaptoReturn = new Map<String,List<String>>();
        Map<String,List<String>> mapofDependency = new Map<String,List<String>>();
        try{
	string AccountQuery = 'Select id,Category__c,Speciality__c 
		               from Account where id = \''+AccountId+ '\' limit 1';

            list<Account> currentAcc = new list<Account>();
            currentAcc = Database.query(AccountQuery);
			
            //geting the Category and Specialty of current account record
			
            string Category = currentAcc[0].Category__c;
            string Speciality = currentAcc[0].Speciality__c;
            
            //getting the list of all Access Master records to determine
	    //the picklist values to be populated based on currentAcc record
			
            string AccessQuery = 'Select id,Request_Type__c,Service_Type__c,
                   Access_Category__c,Access_Speciality__c from
                   Access_Manager__c where Access_Category__c = \''+Category+ '\'
                   and Access_Speciality__c = \''+Speciality+ '\'';
								
            list<Access_Manager__c> AccessManagerList = new list<Access_Manager__c>();
            AccessManagerList = Database.query(AccessQuery);
            
	    //creating dynamic list of request and service picklist values
			
            Set<String> SetRequestType = new Set<String>(); 
            Set<String> SetServiceType = new Set<String>();
            
                for(Access_Manager__c acm : AccessManagerList){
                    if(acm.Request_Type__c != null){
                        SetRequestType.add(acm.Request_Type__c);
                    }
                    if(acm.Service_Type__c != null){
                        SetServiceType.add(acm.Service_Type__c);
                    }
			
			//Assimilating request type (dependent) picklist values 
			for every Service Type (dynamic) picklist value 
			
                    if(!mapofDependency.containsKey(acm.Service_Type__c)){
                        mapofDependency.put(acm.Service_Type__c,
			new List<String>{acm.Request_Type__c});
                    }else{
                        mapofDependency.get(acm.Service_Type__c).add(acm.Request_Type__c);
                    }
                }
				
            //Assimilating all picklist values
			
                if(SetRequestType.size()>0){
                    MaptoReturn.put('SetRequestType',new List<String>(SetRequestType));
                }
                if(SetServiceType.size()>0){
                    MaptoReturn.put('SetServiceType',new List<String>(SetServiceType));
                }
		    //wrapper class
            objWrapper.mapOfValues = MaptoReturn;
            objWrapper.mapOfDependentValue = mapofDependency;
            system.debug('MaptoReturn'+MaptoReturn);
            system.debug('MaptoReturn'+mapofDependency);
            return objWrapper;
            
        }catch(Exception e){
            system.debug('Exception**'+e);
            return null;
        }
    }
    public class PicklistWrapper{
        @AuraEnabled 
        public Map<String,List<String>> mapOfValues;
        @AuraEnabled 
        public Map<String,List<String>> mapOfDependentValue;
    }


}

LWC ( Html )

//CaseRequestComponent.html
<template >

     <!--<lightning-quick-action-panel  title="Quick Action Title">-->
        
            <template if:false={isREcordformVisible}>
            <div >
            <div class="slds-m-around_medium">
                <div class="slds-col modal-header slds-modal__header" style="height: 60px;">
                    <h2 class="title slds-text-heading--medium">New Service Request</h2>
                </div>
                <lightning-combobox name="Service type"
                        value={selectedServiceTypeValue}
                        label="Service Type"
                        placeholder="Select Service type"
                        options={ServicetypeOptions}
                        onchange={handleServiceChange}
                        style="padding: 5px">
                </lightning-combobox>
                
            </div>
            <br/>
            <div class="slds-m-around_medium">
                <lightning-combobox name="Request Type"
                        value={selectedRequestTypeValue}
                        label="Request Type"
                        placeholder="Request Type"
                        onchange={handleRequesttypeChange}
                        options={RequesttypeOptions}>
                        
                </lightning-combobox>
                
            </div>

        </div>
        </template>    
            

LWC ( Js )

import { LightningElement ,api, wire,track} from 'lwc';
import CASE_OBJECT from '@salesforce/schema/Case';
import getDynamicPicklist from '@salesforce/apex/USV_GenerateRequestController.getDynamicPicklist';
export default class GenerateRequestComponent extends LightningElement {

    @api recordId;
    @track ServicetypeOptions = [];
    @track RequesttypeOptions = [];
    @track RequestTypedata = [];
    dependencyMap =[];
 
    requiredServicesOptions;
    topicOfTherapyOptions;
   @api selectedServiceTypeValue;
   @api selectedRequestTypeValue;
   @api selectedTypeOfMeetingValue;
   @api requiredServicesValue;
   @api topicOfTherapyValue;
 
   @wire(getObjectInfo,{objectApiName: CASE_OBJECT})
   casemetadata;   
   connectedCallback(){
    getDynamicPicklist({AccountId: this.recordId})
    .then((data) => {
      var result = data.mapOfValues;
      this.dependencyMap = data.mapOfDependentValue;
        console.log('result',result);
        var serviceTypelst = result['SetServiceType'];
        for(var index in serviceTypelst){
            const option = {
              label: serviceTypelst[index],
              value: serviceTypelst[index]
          };
          this.ServicetypeOptions = [ ...this.ServicetypeOptions, option ];
        }
        
        var requestTypeLst =  result['SetRequestType'];
        for(var index in requestTypeLst){
          const option = {
            label: requestTypeLst[index],
            value: requestTypeLst[index]
        };
        this.RequestTypedata = [ ...this.RequestTypedata,option];
      }
        console.log('Service type', this.ServicetypeOptions);
        console.log('request type', this.RequestTypedata);
      }
    )
    .catch((error) => {  
     console.log('error in fetching getPicklist',error);
    })
   }

 
 handleServiceChange(event) {
  this.RequesttypeOptions = [];
     this.selectedServiceTypeValue=event.target.value;
     console.log('selectedServiceTypeValue' +this.selectedServiceTypeValue);
      //let key = this.RequestTypedata.controllerValues[event.target.value];
      //console.log('key',key);
      let key = this.selectedServiceTypeValue;
     var reqOpt = this.dependencyMap[key];
      for(var index in reqOpt){
        const option = {
          label: reqOpt[index],
          value: reqOpt[index]
      };
      this.RequesttypeOptions = [ ...this.RequesttypeOptions,option];
     }
     console.log('request type',this.RequesttypeOptions);
 }
 
 handleRequesttypeChange(event){
  this.isREcordformVisible=false;
     this.selectedRequestTypeValue=event.target.value;
     console.log('selectedRequestTypeValue',this.selectedRequestTypeValue);
    
     getDependentFields().then(result=>{
      console.log('result'+result);
      for(var i=0;i<result.length;i++){
           
        this.FieldsetVal1 = result[i].split('::');
        let req;
        if(this.FieldsetVal1[2] == 'true'){
         this.req = true;
        }else{
          this.req = false;
        }
        this.dependentdata.push({"label":this.FieldsetVal1[0],"fieldapi":this.FieldsetVal1[1],"required":this.req});  
      }
      console.log(' this.dependentdata',this.dependentdata);
    
    }
    ).catch(error => {
      this.error = error;
      console.log('error in fetching fieildsets')
  });


     getFieldSet({ selectedRequestTypeValue: this.selectedRequestTypeValue})
     .then(result => {
         console.log('result from clas:'+result);
         for(var i=0;i<result.length;i++){
           
             this.FieldsetVal =result[i].split('::');
             let req;
             if(this.FieldsetVal[2]=='true'){
              this.req=true;
             }else{
               this.req=false;
             }
             this.mapData.push({"label":this.FieldsetVal[0],"fieldapi":this.FieldsetVal[1],"required":this.req});  
          
         }
        console.log('mapdata array: ',this.mapData );
         this.isREcordformVisible=true;
         console.log('render recordForm');
     })
     .catch(error => {
         this.error = error;
         console.log('error in fetching fieildsets')
     });



    }
 
}

LWC ( Meta XML )

<?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__RecordAction</target>
  </targets>
   <targetConfigs>
  <targetConfig targets="lightning__RecordAction">
    <!--<actionType>Action</actionType>-->
    <actionType>ScreenAction</actionType>
  </targetConfig>
</targetConfigs>
</LightningComponentBundle>

Do you need to just create a simple picklist to reflect values from a picklist field on any object? Feel free to check out some note-worthy related posts!

Working with Picklists in Apex and Lightning Web Components
Real-time Dependent picklist from Record field values in LWC

Leave a comment

error: Content is protected !!