<lightning-record-edit-form> component in Lightning Web Components (LWC) provides built-in form handling, schema awareness, and database commits without custom Apex. By intercepting the form's onsubmit event in JavaScript, you can execute custom client-side validation rules, format input values, and stop invalid records from submitting before making a server roundtrip.
Standard Salesforce page layouts automatically enforce required fields and validation rules, but custom business processes often demand dynamic client-side checks—such as cross-field dependency validation, regex pattern checks, or conditional data requirements. Building custom edit forms with <lightning-record-edit-form> and <lightning-input-field> allows developers to create tailored multi-column layouts while retaining full control over data submission and error handling.
1. Understanding the Form Submission Lifecycle
Managing record edits with <lightning-record-edit-form> follows a structured event lifecycle:
onload: Fires when record data and schema metadata are fetched from Lightning Data Service (LDS).onsubmit: Intercepted before data is sent to the server. Callingevent.preventDefault()pauses submission so your JavaScript controller can inspectevent.detail.fieldsand run custom validation logic.onsuccess: Fires after the record successfully saves, providing the record ID inevent.detail.id.onerror: Captures server-side validation rule errors, trigger exceptions, and duplicate rule alerts.
- Core Component:
<lightning-record-edit-form>&<lightning-input-field> - Event Hook:
onsubmit={handleSubmit}withevent.preventDefault(). - Error Feedback:
<lightning-messages>for standard banners orShowToastEventfor popups. - Data Submission:
this.template.querySelector('lightning-record-edit-form').submit(fields); - Security Advantage: Automatically respects Object and Field-Level Security (FLS) without custom Apex code.
2. Step-by-Step Implementation: Building the Validated Form
The following example creates a validated Account form that ensures custom conditional criteria are met before saving.
accountRecordForm.html)Structure the form using the Salesforce Lightning Design System (SLDS) grid system.
<template>
<lightning-card title="Create Enterprise Account" icon-name="standard:account">
<div class="slds-p-around_medium">
<lightning-record-edit-form
object-api-name="Account"
onsubmit={handleSubmit}
onsuccess={handleSuccess}
onerror={handleError}>
<!-- Displays standard platform error messages -->
<lightning-messages></lightning-messages>
<div class="slds-grid slds-wrap slds-gutters">
<div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-2">
<lightning-input-field field-name="Name" required></lightning-input-field>
</div>
<div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-2">
<lightning-input-field field-name="Industry" required></lightning-input-field>
</div>
<div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-2">
<lightning-input-field field-name="AnnualRevenue"></lightning-input-field>
</div>
<div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-2">
<lightning-input-field field-name="Phone"></lightning-input-field>
</div>
</div>
<div class="slds-m-top_medium">
<lightning-button
type="submit"
label="Save Account"
variant="brand"
class="slds-m-right_small">
</lightning-button>
<lightning-button
label="Cancel"
variant="neutral"
onclick={handleReset}>
</lightning-button>
</div>
</lightning-record-edit-form>
</div>
</lightning-card>
</template>
accountRecordForm.js)Intercept the submission, execute custom validations, and dispatch toast notifications.
import { LightningElement, api } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { NavigationMixin } from 'lightning/navigation';
export default class AccountRecordForm extends NavigationMixin(LightningElement) {
@api recordId;
handleSubmit(event) {
// Stop the form from submitting automatically
event.preventDefault();
const fields = event.detail.fields;
// Custom Validation Rule 1: Required Name & Industry
if (!fields.Name || !fields.Industry) {
this.showToast('Validation Error', 'Account Name and Industry are required.', 'error', 'dismissable');
return;
}
// Custom Validation Rule 2: Banking accounts must specify Annual Revenue
if (fields.Industry === 'Banking' && (!fields.AnnualRevenue || Number(fields.AnnualRevenue) <= 0)) {
this.showToast(
'Revenue Required',
'Annual Revenue must be greater than 0 for Banking accounts.',
'warning',
'sticky'
);
return;
}
// Submit the validated payload back to Lightning Data Service
this.template.querySelector('lightning-record-edit-form').submit(fields);
}
handleSuccess(event) {
const createdRecordId = event.detail.id;
this.showToast(
'Success',
`Account created successfully with ID: ${createdRecordId}`,
'success',
'dismissable'
);
// Optional: Navigate to the newly created record page
this[NavigationMixin.Navigate]({
type: 'standard__recordPage',
attributes: {
recordId: createdRecordId,
actionName: 'view'
}
});
}
handleError(event) {
this.showToast(
'Error Creating Record',
event.detail.detail || 'An unexpected error occurred.',
'error',
'sticky'
);
}
handleReset() {
const inputFields = this.template.querySelectorAll('lightning-input-field');
if (inputFields) {
inputFields.forEach(field => {
field.reset();
});
}
}
showToast(title, message, variant, mode) {
this.dispatchEvent(
new ShowToastEvent({
title: title,
message: message,
variant: variant,
mode: mode || 'dismissable'
})
);
}
}
3. Common Traps & Developer Best Practices
If you omit
event.preventDefault() in the handleSubmit method, the form will submit the payload to the server immediately before your custom JavaScript validations finish executing. Always call event.preventDefault() first, validate your conditions, and only call submit(fields) when all rules pass.
- Use Native SLDS Grid Utilities: Rely on standard classes like
slds-grid,slds-wrap, andslds-p-around_mediumrather than writing custom CSS margin/padding rules. - Include
<lightning-messages>: Always place<lightning-messages>inside the form so server-side validation rules and trigger exceptions render automatically for the user. - Form Reset Pattern: To clear form fields, iterate over all
<lightning-input-field>nodes usingthis.template.querySelectorAll()and invoke their native.reset()method.
Summary
Implementing record forms with custom validation in Lightning Web Components provides a seamless, responsive experience for Salesforce users. By combining <lightning-record-edit-form> with client-side event interception and toast notifications, developers can enforce complex business requirements cleanly while reducing unnecessary server roundtrips.