<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'
})
);
}
}
}
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.
- User double-clicks a cell, edits the text or ID, and hits enter (the cell highlights green with draft state).
- User clicks the Save button that automatically appears at the top of the table.
handleSave()captures all modified rows viaevent.detail.draftValues.Promise.all()submits all record changes to Salesforce in parallel, ensuring efficient database transactions.
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.
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!