Skip to main content

How to Add Lookup Fields with Inline Editing in Salesforce LWC Datatables

In plain words: The standard Salesforce <lightning-datatable> supports inline editing for text, numbers, and dates out of the box. However, it does not natively support standard lookup search widgets (like picking an Account or a Contact) inside table cells. To add inline editing for relationship fields, you must combine standard datatable draft values with custom cell custom data types or specialized wrapper solutions.

Building high-productivity user interfaces in Salesforce often means letting users edit multiple records directly inside a table without clicking into individual detail pages. While text fields are easy to make editable, relationship lookup fields require a bit more architectural planning.

In this guide, we will explore how to set up inline editing for datatables and handle record updates using the Lightning UI API.

Step 1: Set Up the Project

Create a new Lightning Web Component in your Salesforce DX project using the modern Salesforce CLI:

sf lightning generate component -n lookupDataTable -d force-app/main/default/lwc

Step 2: Build the HTML Template

Open lookupDataTable.html. We will bind our table data, columns, draft values, and the onsave event handler.

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

Step 3: Write the JavaScript Controller

Open lookupDataTable.js. Here we configure our columns (marking them as editable) and implement the handleSave method to process batch updates using the updateRecord UI API utility.

import { LightningElement, track } from 'lwc';
import { updateRecord } from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';

const COLUMNS = [
    { label: 'Name', fieldName: 'Name', editable: true },
    { label: 'Account ID', fieldName: 'AccountId', editable: true },
    { label: 'Phone', fieldName: 'Phone', type: 'phone', editable: true }
];

export default class LookupDataTable extends LightningElement {
    @track data = [
        { Id: '001xx000003DGb2AAG', Name: 'Acme Corp', AccountId: '001xx0000000001AAA', Phone: '555-0199' },
        { Id: '001xx000003DGb3AAG', Name: 'Global Tech', AccountId: '001xx0000000002AAA', Phone: '555-0143' }
    ];
    
    columns = COLUMNS;
    @track draftValues = [];

    async handleSave(event) {
        // 1. Get edited rows from the datatable event detail
        const recordsToSave = event.detail.draftValues;

        // 2. Map draft values into record update promises
        const updatePromises = recordsToSave.map(record => {
            const fields = { ...record };
            return updateRecord({ fields });
        });

        try {
            // 3. Execute all updates simultaneously
            await Promise.all(updatePromises);

            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Success',
                    message: 'Records updated successfully!',
                    variant: 'success'
                })
            );

            // Clear draft values to close the inline edit bar
            this.draftValues = [];
            
        } catch (error) {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error updating records',
                    message: error.body.message,
                    variant: 'error'
                })
            );
        }
    }
}
Developer Trap: Standard Lookups vs. Custom Custom Types
The standard <lightning-datatable> does not render a searchable Salesforce lookup modal inside table cells out of the box when you set editable: true on an ID field; it renders a simple text input. To achieve full lookup search pills inside a datatable cell, you must extend LightningDatatable and build a custom cell component. For most standard projects, editing relationship IDs via text input or utilizing standard record edit forms is recommended unless custom cell datatables are strictly required.
Step-by-Step Batch Saving:
  1. User double-clicks a cell, edits the text or ID, and hits enter (the cell highlights green with draft state).
  2. User clicks the Save button that automatically appears at the top of the table.
  3. handleSave() captures all modified rows via event.detail.draftValues.
  4. Promise.all() submits all record changes to Salesforce in parallel, ensuring efficient database transactions.
360 Card: Key Datatable Editing Properties
  • editable: true: Placed in column definitions to unlock inline editing for specific columns.
  • draft-values={draftValues}: Binds user edits to a local array so the datatable knows which cells are modified.
  • onsave={handleSave}: Fires when the user clicks the Save button on the inline edit panel.
Core Takeaway: Implementing inline editing in LWC datatables requires mapping user draft values into asynchronous record update promises via Promise.all() and the UI API.

Conclusion

Adding inline editing to Lightning Web Component datatables gives users a fast, streamlined experience when managing bulk data. By combining reactive draft values with the power of JavaScript promises and Salesforce UI APIs, you can process batch record edits cleanly and securely.

Happy coding!