This blog post delves into diverse techniques for binding picklist values within LWC and their application in the development process.
Within this LWC component, three distinct picklist fields—Type, Industry, and Rating—are utilized. Let’s delve into how picklist values have been bound for these fields.
1. Employing the UI Object Info API
The initial method for binding picklist values involves utilizing the UI Object Info API. This API enables the retrieval of metadata information pertaining to an object, allowing access to the list of picklist values for a specific field. In this instance, the provided LWC component utilizes the Metadata API to bind picklist values for the Type field sourced from the Account Object.
To leverage the UI Object Info API, we start by importing the ‘getPicklistValues’ function from the ‘lightning/uiObjectInfoApi’ module. Subsequently, we utilize the ‘@wire’ decorator to wire this function to our component. Within the wired property, we map the data values into an array of options, utilizing this array to populate the lightning-combobox component.
Sample Code:
The initial method for binding picklist values involves utilizing the UI Object Info API. This API enables the retrieval of metadata information pertaining to an object, allowing access to the list of picklist values for a specific field. In this instance, the provided LWC component utilizes the Metadata API to bind picklist values for the Type field sourced from the Account Object. To leverage the UI Object Info API, we start by importing the 'getPicklistValues' function from the 'lightning/uiObjectInfoApi' module. Subsequently, we utilize the '@wire' decorator to wire this function to our component. Within the wired property, we map the data values into an array of options, utilizing this array to populate the lightning-combobox component. Sample Code:
Below are the pros and cons of this approach –
Advantages –
- Simplicity: The lightning/uiObjectInfoApi module offers a straightforward and declarative approach to accessing picklist values through a standardized API. This simplicity can facilitate developers in customizing or maintaining your application with greater ease.
- Up-to-Date Information: Utilizing the standard API ensures continuous access to the most current picklist values, eliminating the need for manual updates within an Apex class.
- Consistency: Employing the standard API guarantees uniform picklist values across your organization. It also ensures that these values comply with any custom business logic or validation rules configured on the picklist field.
- Record Type Support: If your object employs record types, this API enables the retrieval of picklist values based on the record type assignments within your organization.
- Wide Support: This functionality is supported for all custom objects and most standard objects.
Drawbacks –
- Performance: Depending on the complexity of your application and the number of picklist fields that need to be retrieved, using the lightning/uiObjectInfoApi module could impact performance by requiring additional client-server round trips.
- API Limits: Depending on the number of API calls you make and the number of picklist fields that need to be retrieved, you may run into API limits or incur additional costs if you are using a third-party API provider.
- Limited Flexibility: While the lightning/uiObjectInfoApi module provides a simple way to retrieve picklist values, it may not offer the same level of flexibility or control as retrieving picklist values from an Apex class. For example, you may not be able to dynamically change the available picklist values based on certain conditions or add custom logic to handle the selected value.
- Not supported for external objects and some of the standard objects are also not supported , make sure to check these salesforce documentation links before implementing- Salesforce Objects Supported by lightning/ui*Api Modules – Salesforce Lightning Component Library & All Supported Objects | User Interface API Developer Guide | Salesforce Developers
2. Utilizing Hardcoded Values in JavaScript for Picklist Options
The secondary method to bind picklist values involves using hardcoded values. Within the provided LWC component, this method is employed to bind the picklist values for the Industry field sourced from the Account Object.
To utilize hardcoded values, we straightforwardly create an array of options within our component and employ it to populate the lightning-combobox component.
JS - // Define an array of industry options industryOptions = [ { label: 'Agriculture', value: 'Agriculture' }, { label: 'Apparel', value: 'Apparel' }, { label: 'Banking', value: 'Banking' }, { label: 'Biotechnology', value: 'Biotechnology' }, { label: 'Chemicals', value: 'Chemicals' } ]; HTML - <lightning-combobox label="Industry" value={accountIndustry} options={industryOptions} onchange={handleAccountIndustryChange}></lightning-combobox>
Below are the pros and cons of this approach –
Downsides –
- Lack of server-side validation : Due to lack of server-side validation, it may cause data inconsistencies if the pick list options only rely on JavaScript, and the options do not match the data stored on the server.s.
- Potential security risks: Improper sanitization of pick list options defined in JavaScript could lead to potential security vulnerabilities, such as cross-site scripting (XSS) attacks.
3. Employing Apex Controller
The third method to bind picklist values involves utilizing an Apex controller. Within the provided LWC component, this approach is employed to bind the picklist values for the Rating field sourced from the Account Object.
To utilize an Apex controller, we first define an Apex method responsible for returning the picklist values. Subsequently, we import this method into our LWC component using the ‘@salesforce/apex’ module. Then, utilizing the ‘@wire’ decorator, we wire the method to our component. Within the wired property, we map the data to an array of options, which is used to populate the lightning-combobox component.
JS - // Import getRatingPicklistValues function from Apex controller import getRatingPicklistValues from '@salesforce/apex/AccountController.getPicklistValues'; // Wire getRatingPicklistValues function from Apex controller to the component @wire(getRatingPicklistValues, {}) // Define a wired property for rating picklist values wiredRatingPicklistValues({ error, data }) { // If data is returned from the wire function if (data) { // Map the data to an array of options this.ratingOptions = data.map(option => { return { label: option.label, value: option.value }; }); } // If there is an error else if (error) { // Log the error to the console console.error(error); } } HTML - <lightning-combobox label="Rating" value={accountRating} options={ratingOptions} onchange={handleAccountRatingChange}></lightning-combobox> Apex - @AuraEnabled(cacheable=true) public static List<Map<String, String>> getPicklistValues() { List<Schema.PicklistEntry> entries = Account.Rating.getDescribe().getPicklistValues(); List<Map<String, String>> values = new List<Map<String, String>>(); for (Schema.PicklistEntry entry : entries) { Map<String, String> valueMap = new Map<String, String>(); valueMap.put('label', entry.getLabel()); valueMap.put('value', entry.getValue()); values.add(valueMap); } return values; }
Below are the pros and cons of this approach –
Advantages –
Enhanced Control: Accessing picklist values from an Apex class grants greater control over their display and utilization within your application. This includes dynamic adjustments to available picklist values based on specific conditions or the incorporation of custom logic to manage selected values.
Improved Performance: Employing a cached, server-side call for retrieving picklist values enhances application performance by minimizing the number of client-server round trips necessary to obtain these values.
Versatility: Exposing a picklist values method through an Apex class enables its utilization across various components, pages, or even multiple applications. This facilitates code reusability and ensures a consistent user experience throughout your organization.
Downsides –
- Maintenance: If picklist values change frequently, it may be more difficult to keep an Apex class up to date compared to using a standard picklist field in the UI. You would need to update the Apex class every time the picklist values change.No Support for Record Types – Currently there is no support for Getting Picklist values based on Record Type, you need to make your own logic to customize the options – Getting Picklist values based on Record Type | IdeaExchange (salesforce.com)
Below is the complete sample code, where we showed the below 3 ways –
- Bind Type field by Using UI Object Info APIBind Industry field by Using Hardcoded values in JS for PickList OptionsBind Rating field by Using Apex Controller
HTML
<template> <lightning-card title="Account Form"> <div class="slds-m-around_medium"> <lightning-combobox label="Type" value={accountType} options={typeOptions} onchange={handleAccountTypeChange}> </lightning-combobox> <lightning-combobox label="Industry" value={accountIndustry} options={industryOptions} onchange={handleAccountIndustryChange}></lightning-combobox> <lightning-combobox label="Rating" value={accountRating} options={ratingOptions} onchange={handleAccountRatingChange}></lightning-combobox><br /> Selected Type - {accountType} <br /> Selected Industry - {accountIndustry} <br /> Selected Rating - {accountRating} </div> </lightning-card> </template>
JS
// Import LightningElement and wire decorator from LWC module import { LightningElement, wire } from 'lwc'; // Import getPicklistValues function from uiObjectInfoApi module import { getPicklistValues } from 'lightning/uiObjectInfoApi'; // Import getRatingPicklistValues function from Apex controller import getRatingPicklistValues from '@salesforce/apex/AccountController.getPicklistValues'; // Import constant TYPE_FIELD from Account schema import TYPE_FIELD from '@salesforce/schema/Account.Type'; export default class AccountForm extends LightningElement { // Initialize properties for the component accountType = ''; // Set default value for accountType accountIndustry = ''; // Set default value for accountIndustry accountRating = ''; // Set default value for accountRating typeOptions = []; // Initialize typeOptions as an empty array ratingOptions = []; // Initialize ratingOptions as an empty array // Define an array of industry options industryOptions = [ { label: 'Agriculture', value: 'Agriculture' }, { label: 'Apparel', value: 'Apparel' }, { label: 'Banking', value: 'Banking' }, { label: 'Biotechnology', value: 'Biotechnology' }, { label: 'Chemicals', value: 'Chemicals' } ]; // Wire getPicklistValues function from uiObjectInfoApi module to the component @wire(getPicklistValues, { recordTypeId: '012000000000000AAA', // Specify record type ID , if no record type is there specify default record type fieldApiName: TYPE_FIELD // Specify field API name }) // Define a wired property for type picklist values wiredTypePicklistValues({ error, data }) { // If data is returned from the wire function if (data) { // Map the data values to an array of options this.typeOptions = data.values.map(option => { return { label: option.label, value: option.value }; }); } // If there is an error else if (error) { // Log the error to the console console.error(error); } } // Wire getRatingPicklistValues function from Apex controller to the component @wire(getRatingPicklistValues, {}) // Define a wired property for rating picklist values wiredRatingPicklistValues({ error, data }) { // If data is returned from the wire function if (data) { // Map the data to an array of options this.ratingOptions = data.map(option => { return { label: option.label, value: option.value }; }); } // If there is an error else if (error) { // Log the error to the console console.error(error); } } // Define a method to handle changes to the account type handleAccountTypeChange(event) { // Set the account type to the selected value this.accountType = event.target.value; } // Define a method to handle changes to the account industry handleAccountIndustryChange(event) { // Set the account industry to the selected value this.accountIndustry = event.target.value; } // Define a method to handle changes to the account rating handleAccountRatingChange(event) { // Set the account rating to the selected value this.accountRating = event.target.value; } }
Apex
public with sharing class AccountController { /** * Retrieves the picklist values for the Rating field of the Account object. * @return A list of maps, where each map contains the label and value of a picklist value. */ @AuraEnabled(cacheable=true) public static List<Map<String, String>> getPicklistValues() { // Retrieve the picklist values for the Rating field of the Account object. List<Schema.PicklistEntry> entries = Account.Rating.getDescribe().getPicklistValues(); // Create a list to hold the label and value of each picklist value. List<Map<String, String>> values = new List<Map<String, String>>(); // Loop through the picklist values and add the label and value to the list. for (Schema.PicklistEntry entry : entries) { // Create a map to hold the label and value of the picklist value. Map<String, String> valueMap = new Map<String, String>(); // Add the label and value to the map. valueMap.put('label', entry.getLabel()); valueMap.put('value', entry.getValue()); // Add the map to the list. values.add(valueMap); } // Return the list of maps. return values; }