Skip to main content

How to Implement Dynamic Picklist in LWC Datatable with Inline Editing

In plain words: An inline-editable picklist in an LWC datatable lets users update dropdown choices directly within tabular data rows without navigating away from the screen or opening a full edit modal.

Standard Salesforce lightning-datatable components support text and number inline editing out of the box. However, dynamic picklists require fetching metadata dynamically via Apex schema methods and wiring them into your table columns.

Prerequisites

  • Basic knowledge of Lightning Web Components (LWC) and Apex classes.
  • Salesforce Developer Edition, Sandbox, or Scratch Org.
  • Salesforce CLI installed for deployment.

Step 1: Create the Apex Controller

First, create an Apex class that inspects the field schema and returns available picklist entries dynamically.

public with sharing class PicklistController {
    @AuraEnabled(cacheable=true)
    public static Map<String, List<String>> getPicklistValues(String objectName, String fieldName) {
        Map<String, List<String>> picklistValuesMap = new Map<String, List<String>>();
        
        Schema.SObjectType targetType = Schema.getGlobalDescribe().get(objectName);
        if (targetType == null) {
            return picklistValuesMap;
        }

        Schema.DescribeSObjectResult describeResult = targetType.getDescribe();
        Schema.DescribeFieldResult fieldResult = describeResult.fields.getMap().get(fieldName)?.getDescribe();
        
        if (fieldResult != null && fieldResult.isAccessible() && fieldResult.isPicklistField()) {
            List<String> values = new List<String>();
            for (Schema.PicklistEntry entry : fieldResult.getPicklistValues()) {
                if (entry.isActive()) {
                    values.add(entry.getValue());
                }
            }
            picklistValuesMap.put(fieldName, values);
        }
        
        return picklistValuesMap;
    }
}
Trap Alert: Always enforce Field-Level Security (FLS) by checking isAccessible() and filtering with entry.isActive() to prevent inactive picklist entries from appearing in edit dropdowns.

Step 2: Build the Datatable Component Template

Create an LWC named picklistInDatatable. In your template file, implement the lightning-datatable with save event listeners and draft value tracking.

<template>
    <lightning-card title="Editable Datatable with Picklist" icon-name="standard:record">
        <div class="slds-p-around_medium">
            <lightning-datatable
                key-field="Id"
                data={data}
                columns={columns}
                onsave={handleSave}
                draft-values={draftValues}
                hide-checkbox-column>
            </lightning-datatable>
        </div>
    </lightning-card>
</template>

Step 3: Implement JavaScript Controller Logic

Wire the Apex controller, define columns, and manage changes using draftValues:

import { LightningElement, wire, api, track } from 'lwc';
import { refreshApex } from '@salesforce/apex';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import getPicklistValues from '@salesforce/apex/PicklistController.getPicklistValues';

const ACTIONS = [
    { label: 'Edit', name: 'edit' },
    { label: 'Delete', name: 'delete' }
];

const COLUMNS = [
    { label: 'Name', fieldName: 'Name', editable: true },
    { 
        label: 'Status', 
        fieldName: 'Status__c', 
        editable: true, 
        type: 'text' 
    },
    { type: 'action', typeAttributes: { rowActions: ACTIONS } }
];

export default class PicklistInDatatable extends LightningElement {
    @api recordId;
    @track data = [];
    @track draftValues = [];
    columns = COLUMNS;
    wiredPicklistResult;

    @wire(getPicklistValues, { objectName: 'Account', fieldName: 'Type' })
    wiredValues(result) {
        this.wiredPicklistResult = result;
        if (result.error) {
            this.showToast('Error', 'Failed to load picklist entries', 'error');
        }
    }

    handleSave(event) {
        const updatedFields = event.detail.draftValues;
        
        // Execute DML update logic via Apex or standard uiRecordApi updateRecord
        this.showToast('Success', 'Records updated successfully', 'success');
        
        refreshApex(this.wiredPicklistResult);
        this.draftValues = [];
    }

    showToast(title, message, variant) {
        this.dispatchEvent(new ShowToastEvent({ title, message, variant }));
    }
}
360 Architecture Summary:
  • Metadata Fetching: Handled dynamically via cacheable Apex schema calls.
  • Custom Data Types: For custom picklist cell editing, extend LightningDatatable with a custom template type.
  • Cache Invalidation: Always invoke refreshApex() after DML operations.

Step 4: Deploy and Configure Lightning Page

Deployment Steps:
  • Deploy your Apex class and LWC component using Salesforce CLI: sf project deploy start.
  • In Salesforce Setup, navigate to Lightning App Builder.
  • Open your target Record Page or App Page and drag picklistInDatatable onto the layout canvas.
  • Click Save and Activate.
Core Takeaway: Dynamic schema access in Apex combined with LWC reactive wire adapters provides a scalable, metadata-driven UI without hardcoding field options in client-side code.