Project: A Professional Lead Capture Component
By the end of this lesson, you'll be able to:
- Combine input components, validation, and choice-based fields into one form
- Handle submission with a loading state and toast feedback
- Create a new Lead record using Lightning Data Service
Prerequisites: "Submission, Loading States, and Toast Notifications"
What We're Building
A leadCaptureForm component with:
- Text, email, and picklist-style fields (Lesson 1) with
requiredvalidation (Lesson 3). - A
lightning-radio-groupfor Lead Source (Lesson 2). - A submit button with a loading spinner and disabled state while submitting (Lesson 4).
- Success and error toast notifications (Lesson 4).
- A real
createRecordcall against the standard Lead object — no Apex needed, per Module 6/7's decision checklist, since this is a straightforward single-record create.
The Component
import { LightningElement } from 'lwc';
import { createRecord } from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import LEAD_OBJECT from '@salesforce/schema/Lead';
import FIRST_NAME_FIELD from '@salesforce/schema/Lead.FirstName';
import LAST_NAME_FIELD from '@salesforce/schema/Lead.LastName';
import COMPANY_FIELD from '@salesforce/schema/Lead.Company';
import EMAIL_FIELD from '@salesforce/schema/Lead.Email';
import LEAD_SOURCE_FIELD from '@salesforce/schema/Lead.LeadSource';
export default class LeadCaptureForm extends LightningElement {
firstName = '';
lastName = '';
company = '';
email = '';
leadSource = '';
isSubmitting = false;
get leadSourceOptions() {
return [
{ label: 'Web', value: 'Web' },
{ label: 'Referral', value: 'Referral' },
{ label: 'Trade Show', value: 'Trade Show' },
];
}
handleFirstNameChange(event) { this.firstName = event.target.value; }
handleLastNameChange(event) { this.lastName = event.target.value; }
handleCompanyChange(event) { this.company = event.target.value; }
handleEmailChange(event) { this.email = event.target.value; }
handleLeadSourceChange(event) { this.leadSource = event.detail.value; }
isFormValid() {
return [...this.template.querySelectorAll('lightning-input')]
.reduce((valid, field) => field.reportValidity() && valid, true);
}
async handleSubmit() {
if (!this.isFormValid()) {
return;
}
this.isSubmitting = true;
const recordInput = {
apiName: LEAD_OBJECT.objectApiName,
fields: {
[FIRST_NAME_FIELD.fieldApiName]: this.firstName,
[LAST_NAME_FIELD.fieldApiName]: this.lastName,
[COMPANY_FIELD.fieldApiName]: this.company,
[EMAIL_FIELD.fieldApiName]: this.email,
[LEAD_SOURCE_FIELD.fieldApiName]: this.leadSource,
},
};
try {
await createRecord(recordInput);
this.dispatchEvent(new ShowToastEvent({
title: 'Lead Captured',
message: `${this.firstName} ${this.lastName} was added successfully.`,
variant: 'success',
}));
this.resetForm();
} catch (error) {
this.dispatchEvent(new ShowToastEvent({
title: 'Could Not Save Lead',
message: error.body?.message ?? 'An unexpected error occurred.',
variant: 'error',
}));
} finally {
this.isSubmitting = false;
}
}
resetForm() {
this.firstName = '';
this.lastName = '';
this.company = '';
this.email = '';
this.leadSource = '';
}
}
isFormValid() calls reportValidity() (Lesson 3) on every lightning-input at once using reduce, so a single click surfaces every validation error rather than stopping at the first one.
Why This Matters in Real Projects
This is a realistic, deployable Lead intake form — the exact kind of component a real Salesforce project needs constantly, and it's built entirely from base components, LDS, and the loading/toast pattern, with no Apex whatsoever.
Exercise
Add a Phone field (lightning-input type="tel", not required) to the form, bound to a phone property.
Show hint
Follow the same pattern as the existing fields.
Exercise
Challenge: explain, as a comment, why isFormValid() uses reduce to check every field rather than returning early on the first invalid one.
Show hint
Think about what reportValidity() does as a side effect on each field.
Project: A Professional Lead Capture Component Quiz
My Notes
Log in to keep private notes on this lesson.
Questions about this lesson
No questions yet — be the first to ask.
Log in to ask a question about this lesson.
Summary
A hands-on capstone bringing together every lesson in this module into one realistic, production-quality Lead capture form.