-
-
Save anilsomasundaran/9b331680f4ac05d7421837820068ff07 to your computer and use it in GitHub Desktop.
Custom Dependent Picklist in LWC using ObjectInfo API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<lightning-layout horizontal-align="space"> | |
<lightning-layout-item padding="around-small"> | |
<lightning-combobox | |
name="progress" | |
label="Status" | |
value={parentValue} | |
options={controlOptions} | |
onchange={handleControlChange} ></lightning-combobox> | |
</lightning-layout-item> | |
<lightning-layout-item padding="around-small"> | |
<lightning-combobox | |
class="dependent" | |
name="progress" | |
label="Status" | |
value={dependentValue} | |
options={dependentOptions} | |
onchange={handleDependentChange} disabled={isDisabled}></lightning-combobox> | |
</lightning-layout-item> | |
</lightning-layout> | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { LightningElement,api,wire, track } from 'lwc'; | |
import { getObjectInfo,getPicklistValues,getPicklistValuesByRecordType } from 'lightning/uiObjectInfoApi'; | |
export default class DependentPicklist extends LightningElement { | |
//public attribute for object selection | |
@api | |
objectApiName; | |
//Public attribute for controlling picklist field | |
@api | |
controlFieldName; | |
//Public attribute for dependent picklist field | |
@api | |
dependentFieldName; | |
//Public attribute for recordtype id | |
@api | |
recordTypeId=''; | |
//Public attribute for selected dependent picklist value | |
@api | |
dependentValue = ''; | |
//Public attribute for selected controlling picklist value | |
@api | |
parentValue =''; | |
//to stroe controlling picklist value options | |
controlOptions =[]; | |
//to stroe dependent picklist value options based on the controlling picklist value | |
dependentOptions = []; | |
data = {}; | |
//to enable/disable the dependent picklist field in the UI - disabled it initially | |
isDisabled = true; | |
@track | |
parentField = ''; | |
dependentField = ''; | |
//Wire method which fetches the object detatils with all the dependent picklist fields, record types, field details etc | |
//based on the objectAPIName parameter | |
@wire(getObjectInfo, { objectApiName: '$objectApiName' }) | |
objectInfo({error,data}) { | |
if (data) { | |
//set the default recordtype id if there is no given value | |
if(!this.recordTypeId) { | |
this.recordTypeId = data.defaultRecordTypeId; | |
} | |
//Check if any dependent picklist fields available for the consdiered object | |
if(!(Object.keys(data.dependentFields).length === 0 && data.dependentFields.constructor === Object)){ | |
//check the given controlling field name is valid for this object or not, otherwise throw an appropriate error | |
if(data.dependentFields.hasOwnProperty(this.controlFieldName)){ | |
//console.log(data.dependentFields.hasOwnProperty(this.controlFieldName)); | |
//check the given dependent field name is valid for this object or not, otherwise throw an appropriate error | |
if(!data.dependentFields[this.controlFieldName].hasOwnProperty(this.dependentFieldName)) { | |
console.log('error') | |
return; | |
} | |
//if the fields are valid, then pass the fieldAPIName in appropriate for the getPicklistValue object info wire method | |
//basically, controlling the wire parameters - no possibilty for imperative accessibility to UIObjectInfo API | |
this.parentField = this.generateFieldAPIName(this.controlFieldName); | |
this.dependentField = this.generateFieldAPIName(this.dependentFieldName); | |
} | |
else { | |
console.log('error') | |
return; | |
} | |
} | |
} | |
} | |
//fethch the dependent picklist values based on the recordtype id and fieldAPI details | |
@wire(getPicklistValues, { recordTypeId: '$recordTypeId', fieldApiName: '$dependentField' }) | |
fetchDependentOptions( {error , data }) { | |
if(data) { | |
const controlKeys = {}; | |
//Handling the validFor value which denotes the controlling fields. | |
//check the json format, controllerValues in field:index format and converts it into index:field format | |
Object.keys(data.controllerValues).forEach((key) => { | |
Object.defineProperty(controlKeys, data.controllerValues[key], { | |
value: key, | |
writable: false | |
}); | |
//create a dependent data skelton | |
Object.defineProperty(this.data, key, { | |
value : {values : [], default: false , defaultValue : ''}, | |
writable : true | |
}); | |
}); | |
//dependent data should be formatted as controllingField value as the key and related dependent options in an array | |
//no need to iterate again when the controlling field value changes so this format would be helpful | |
data.values.forEach((val) => { | |
let option = {label : val.label, value : val.value}; | |
let isDefault = val.value === data.defaultValue.value ? true : false ; | |
val.validFor.forEach((key) => { | |
this.data[controlKeys[key]].values.push(option); | |
if(isDefault) { | |
this.data[controlKeys[key]].default = isDefault; | |
this.data[controlKeys[key]].defaultValue = val.value; | |
} | |
}); | |
}); | |
//set the dependent options once the dependent data is ready | |
this.setDependentOptions(); | |
//console.log(controlKeys); | |
//console.log(this.data); | |
}else{ | |
//handle the errors | |
console.log(JSON.stringify(error)); | |
} | |
} | |
//fethch the controlling picklist values based on the recordtype id and fieldAPI details | |
@wire(getPicklistValues,{ recordTypeId: '$recordTypeId', fieldApiName: '$parentField'}) | |
fetchControlOption( {error , data }) { | |
if(data) { | |
//sets the options to contriolling field | |
this.controlOptions = data.values.map((option) => { | |
return {label : option.label, value : option.value}; | |
}); | |
//default value for the controlling field | |
this.parentValue = data.defaultValue.hasOwnProperty('value') ? data.defaultValue.value : ''; | |
//initating to set the dependent option in the field | |
this.setDependentOptions(); | |
}else{ | |
//handle the errors in an appropriate way | |
console.log(JSON.stringify(error)); | |
} | |
} | |
setDependentOptions(){ | |
//only sets the dependent picklist options only if there any valid selection, valid depdendent data for the selected value | |
if(this.parentValue && this.data && this.data.hasOwnProperty(this.parentValue)) { | |
this.isDisabled = false; | |
//fetching the options from the data array using the controlling value as index | |
let selectOptions = this.data[this.parentValue]; | |
//sets the dependent options to the field | |
this.dependentOptions = selectOptions.values; | |
//set the default value | |
if(selectOptions.default){ | |
this.dependentValue = selectOptions.defaultValue; | |
} | |
} | |
} | |
/*Handler for onchange event which initiate a custom event and set the value in the corresponding output attribute */ | |
handleControlChange(event) { | |
this.parentValue = event.detail.value; | |
this.setDependentOptions(); | |
this.dispatchEvent(new CustomEvent('controlchange',{detail : {value : this.parentValue}})); | |
} | |
/*Handler for onchange event which initiate a custom event and set the value in the corresponding output attribute */ | |
handleDependentChange(event) { | |
this.dependentValue = event.detail.value; | |
this.dispatchEvent(new CustomEvent('dependentchange',{detail : {value : this.dependentValue}})); | |
} | |
//define the fieldAPIName for the getPickListValue UI objectinfo api | |
generateFieldAPIName(fieldName) { | |
return {"objectApiName": this.objectApiName,"fieldApiName": fieldName }; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> | |
<apiVersion>49.0</apiVersion> | |
<isExposed>true</isExposed> | |
<targets> | |
<target>lightning__AppPage</target> | |
<target>lightning__RecordPage</target> | |
<target>lightning__HomePage</target> | |
<targets> | |
</LightningComponentBundle> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment