Let’s assume a use case where a company sells to two types of clients:
- Enterprise Clients
- Retail Clients
Each division uses different Sales Processes, so they require:
- Different Record Types
- Different values for both a controlling picklist and a dependent picklist
Opportunity Object Record Types:
Enterprise_SalesRetail_Sales
Controlling Picklist Field: Solution_Type__c
(Custom picklist to identify the type of solution sold)
๐ก Values per Record Type:
| Solution_Type__c | Enterprise_Sales | Retail_Sales |
|---|---|---|
| Cloud Services | โ Yes | โ No |
| On-Premise Licensing | โ Yes | โ No |
| Hardware Bundle | โ Yes | โ Yes |
| Point of Sale Systems | โ No | โ Yes |
| Subscriptions | โ No | โ Yes |
| Marketing Kits | โ No | โ Yes |
Dependent Picklist Field: Product_Type__c
(Dependent on Solution_Type__c)
| Solution_Type__c | Product_Type__c Values |
|---|---|
| Cloud Services | SaaS, IaaS, PaaS |
| On-Premise Licensing | Windows Server, SQL, Exchange |
| Hardware Bundle | Laptops, Servers, Network Gear |
| Point of Sale Systems | POS Machines, Thermal Printers, Barcode Scanners |
| Subscriptions | Monthly Plan, Yearly Plan, Trial |
| Marketing Kits | Flyers, Banners, Swag |
Based on the provided setup, the following LWC displays the ‘Solution Type’ picklist values based on the selected record type, and dynamically shows the ‘Product Type’ picklist values based on both the selected record type and the chosen ‘Solution Type’ (controlling field).
LWC Name: opportunityPicker.html
<template>
<lightning-card title="Opportunity Selection" icon-name="standard:picklist_choice">
<lightning-layout class="slds-var-m-around_medium" multiple-rows>
<!-- Row 1: Picklists -->
<lightning-layout-item class="slds-p-around_medium" size="4" flexibility="auto">
<lightning-combobox
label="Record Type"
value={selectedRecordType}
options={recordTypeOptions}
onchange={handleRecordTypeChange}>
</lightning-combobox>
</lightning-layout-item>
<lightning-layout-item class="slds-p-around_medium" size="4" flexibility="auto">
<lightning-combobox
label="Solution Type"
value={selectedSolutionType}
options={solutionTypeOptions}
onchange={handleSolutionTypeChange}>
</lightning-combobox>
</lightning-layout-item>
<lightning-layout-item class="slds-p-around_medium" size="4" flexibility="auto">
<lightning-combobox
label="Product Type"
value={selectedProductType}
options={filteredProductTypeOptions}
onchange={handleProductTypeChange}>
</lightning-combobox>
</lightning-layout-item>
<!-- Row 2: Selected Values -->
<lightning-layout class="slds-m-top_medium">
<lightning-layout-item class="slds-p-around_medium" size="12" flexibility="auto">
<p><strong>Selected Record Type:</strong> {selectedRecordType}</p>
<br/>
<p><strong>Selected Solution Type:</strong> {selectedSolutionType}</p>
<br/>
<p><strong>Selected Product Type:</strong> {selectedProductType}</p>
</lightning-layout-item>
</lightning-layout>
</lightning-layout>
</lightning-card>
</template>LWC JS: opportunityPicker.js
import { LightningElement, wire, api } from 'lwc';
import { getPicklistValues, getPicklistValuesByRecordType } from "lightning/uiObjectInfoApi";
import OPPORTUNITY_OBJECT from "@salesforce/schema/Opportunity";
import SOLUTION_TYPE_FIELD from '@salesforce/schema/Opportunity.Solution_Type__c';
import PRODUCT_TYPE_FIELD from '@salesforce/schema/Opportunity.Product_Type__c';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
export default class OpportunityPicker extends LightningElement {
@api recordId; // Opportunity ID
//Picklist Options
recordTypeOptions = [];
solutionTypeOptions = [];
allproductTypeMetadata = [];
productTypeOptions = [];
filteredProductTypeOptions = [];
//picklist selected values
selectedRecordType = '';
selectedSolutionType = '';
selectedProductType = '';
// Fetch Record Types
@wire(getObjectInfo, { objectApiName: OPPORTUNITY_OBJECT })
objectInfoHandler({ data, error }) {
if (data) {
const rtInfos = data.recordTypeInfos;
const rtList = Object.values(rtInfos)
.filter(rt => rt.available && !rt.master) // Exclude Master record type
.map(rt => ({
label: rt.name,
value: rt.recordTypeId
}));
this.recordTypeOptions = rtList;
} else if (error) {
console.error('Error fetching record types: ', error);
}
}
// Fetch Product Families
@wire(getPicklistValuesByRecordType, {
objectApiName: OPPORTUNITY_OBJECT,
recordTypeId: '$selectedRecordType'
})
wiredSolutionTypes({ data, error }) {
if (data) {
if (data.picklistFieldValues && data.picklistFieldValues.Solution_Type__c) {
this.solutionTypeOptions = data.picklistFieldValues.Solution_Type__c.values;
} else {
console.warn('No picklist values found for Solution_Type__c.');
}
} else if (error) {
console.error('Error fetching picklist values:', error);
}
}
// Get the dependent picklist values for PRODUCT_TYPE_FIELD (dependent picklist) based on selected Solution Type
@wire(getPicklistValues, { recordTypeId: "$selectedRecordType", fieldApiName: PRODUCT_TYPE_FIELD })
wiredProductTypePicklist({ data, error }) {
if (data) {
this.allproductTypeMetadata = data;
this.productTypeOptions = data.values;
} else if (error) {
console.error('Error fetching picklist values:', error);
}
}
handleRecordTypeChange(event){
this.selectedRecordType = event.target.value;
this.selectedSolutionType = '';
this.selectedProductType = '';
console.log(this.selectedRecordType);
}
handleSolutionTypeChange(event){
this.selectedSolutionType = event.target.value;
const selectedSolutionTypeValue = this.allproductTypeMetadata.controllerValues[this.selectedSolutionType];
this.filteredProductTypeOptions = this.allproductTypeMetadata.values.filter(option =>
option.validFor.includes(selectedSolutionTypeValue)
);
}
handleProductTypeChange(event){
this.selectedProductType = event.target.value;
}
}LWC XML: opportunityPicker.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>63.0</apiVersion>
<isExposed>true</isExposed>
<masterLabel>Dynamic Picklist values</masterLabel>
<targets>
<target>lightning__RecordPage</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__RecordPage">
<objects>
<object>Opportunity</object>
</objects>
</targetConfig>
</targetConfigs>
</LightningComponentBundle>