Editable Picklist in LWC Table?

When working with editable records in Lightning Web Components (LWC), you may run into situations where you want to display fields in a table-like structure, iterate over them using for:each
, and allow users to edit certain fields. For text or number fields, the lightning-input
component works fine, but for a picklist field you need to use lightning-combobox
. The main challenge here is twofold: first, how to render a picklist dynamically, and second, how to handle updates when the user changes values in any field.
The best solution for rendering picklist fields in LWC is by using lightning-combobox
. Salesforce provides a wire adapter called getPicklistValues
which fetches picklist values for a specific field, based on its record type. With this, you can bind picklist values to the options
attribute of lightning-combobox
. Once a user makes a selection, you can capture the change event and update your list of records accordingly.
Here is how you can modify your component:
<template for:each={oppProds} for:item="oppProd" for:index="index">
<tr key={oppProd.Id}>
<td>
<lightning-input
label="Name"
value={oppProd.Name}
data-field="Name"
disabled="true"
class="slds-m-bottom_x-small">
</lightning-input>
</td>
<td>
<lightning-combobox
label="Status"
value={oppProd.Status__c}
data-field="Status__c"
data-index={index}
options={statusOptions}
onchange={handleStatusChange}
class="slds-m-bottom_x-small">
</lightning-combobox>
</td>
<td>
<lightning-input
label="Estimated Contracts"
value={oppProd.Estimated_Conctracts__c}
data-field="Estimated_Conctracts__c"
data-index={index}
onchange={handleChange}
class="slds-m-bottom_x-small">
</lightning-input>
</td>
<td>
<lightning-input
label="Estimated Members"
value={oppProd.Estimated_Members__c}
data-field="Estimated_Members__c"
data-index={index}
onchange={handleChange}
class="slds-m-bottom_x-small">
</lightning-input>
</td>
</tr>
</template>
In this HTML code, we iterate through a list of records oppProds
and display them row by row using for:each
. The lightning-input
is used for name, contracts, and members, while lightning-combobox
is used for the Status picklist. The options={statusOptions}
dynamically populates picklist values, and data-index={index}
helps track which row is being updated. The onchange
events call different handlers (handleStatusChange
or handleChange
) to capture updated values and store them back into the JavaScript array of records.
The corresponding JavaScript controller would look like this:
import { LightningElement, wire, track } from 'lwc';
import { getPicklistValues } from 'lightning/uiObjectInfoApi';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import OPP_OBJECT from '@salesforce/schema/OpportunityLineItem'; // Replace with your object
import STATUS_FIELD from "@salesforce/schema/OpportunityLineItem.Status__c"; // Replace with your picklist field
export default class EditableTableWithPicklist extends LightningElement {
@track oppProds = [];
@track statusOptions = [];
// Fetch object metadata
@wire(getObjectInfo, { objectApiName: OPP_OBJECT })
oppMetadata;
// Fetch picklist values based on record type
@wire(getPicklistValues, {
recordTypeId: "$oppMetadata.data.defaultRecordTypeId",
fieldApiName: STATUS_FIELD
})
picklistResults({ error, data }) {
if (data) {
this.statusOptions = data.values;
} else if (error) {
console.error('Error fetching picklist values', error);
}
}
handleStatusChange(event) {
const field = event.target.dataset.field; // Status__c
const value = event.detail.value; // Selected value
const index = event.target.dataset.index; // Record index
this.oppProds[index][field] = value;
}
handleChange(event) {
const field = event.target.dataset.field;
const value = event.detail.value;
const index = event.target.dataset.index;
this.oppProds[index][field] = value;
}
}
This JavaScript code imports wire adapters getObjectInfo
and getPicklistValues
to fetch object metadata and dynamic picklist values. The statusOptions
property holds the list of picklist options fetched from Salesforce. When a user changes the Status field, the handleStatusChange
method updates the relevant record in the oppProds
array using the index. Similarly, the handleChange
method updates other editable fields like contracts and members. By using data-field
and data-index
, the code ensures the correct row and field get updated in memory without directly saving to the database yet.
Alternative Approaches
If you don’t want to use getPicklistValues
, you can also define picklist options statically in your JavaScript file like this:
statusOptions = [
{ label: 'Open', value: 'Open' },
{ label: 'In Progress', value: 'In Progress' },
{ label: 'Closed', value: 'Closed' }
];
In this approach, the picklist options are hardcoded inside the JavaScript controller. This means the lightning-combobox
will always display the same static values regardless of changes in Salesforce metadata or record types. It is useful for simple scenarios where the picklist values rarely change, such as fixed status indicators. However, this approach lacks flexibility compared to using getPicklistValues
, and future modifications to picklist values in Salesforce would not automatically reflect in your component.
Final Thoughts
By using lightning-combobox
together with getPicklistValues
, you can easily render picklist fields in a loop with for:each
. Handling the change events with data-field
and data-index
makes it straightforward to update the correct record in memory. After collecting all changes, you can send the modified oppProds
array back to Apex for saving into the database. This design ensures your LWC component remains scalable, dynamic, and aligned with Salesforce metadata.
Job-Oriented Salesforce Course with Real-Time Projects and Money Back Guarantee
Our Salesforce course is expertly designed to provide a comprehensive understanding of the Salesforce platform, equipping you with essential skills to excel in the CRM industry. The curriculum covers key modules like Salesforce Admin, Developer, and AI, combining theoretical knowledge with hands-on practice. By working on real-world projects and interactive exercises, you’ll gain the expertise to solve complex business challenges using Salesforce solutions. Our skilled instructors ensure you develop both technical proficiency and industry-relevant insights to succeed in the Salesforce ecosystem.
Beyond technical skills, our Salesforce Training in Australia includes personalized mentorship, certification support, and interview preparation to elevate your career opportunities. You’ll have access to extensive study materials, hands-on project experience, and continuous guidance throughout your learning journey. By the end of the course, you’ll be well-prepared for certification exams and possess the practical problem-solving abilities that employers seek. Tak the first step toward your Salesforce career—Enroll in a Free Demo today!