Project: Lead Management Application
By the end of this lesson, you'll be able to:
- Combine a datatable, a record form, and LDS create into one cohesive Lead management feature
- Refresh a list after a related create operation
- Apply this course's form validation and toast feedback patterns together
Prerequisites: Module 18: "Project: Convert a Desktop Component to Responsive"
What We're Building
A leadManager component with a lightning-datatable (Module 10) listing open Leads, and a "New Lead" form (Module 8's reportValidity() pattern) that creates a Lead via createRecord (Module 6) and refreshes the list on success.
The Component
import { LightningElement, wire } from 'lwc';
import { createRecord } from 'lightning/uiRecordApi';
import { refreshApex } from '@salesforce/apex';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import getOpenLeads from '@salesforce/apex/LeadController.getOpenLeads';
import LEAD_OBJECT from '@salesforce/schema/Lead';
import COMPANY_FIELD from '@salesforce/schema/Lead.Company';
import LAST_NAME_FIELD from '@salesforce/schema/Lead.LastName';
const COLUMNS = [
{ label: 'Name', fieldName: 'name', type: 'text', sortable: true },
{ label: 'Company', fieldName: 'company', type: 'text', sortable: true },
{ label: 'Status', fieldName: 'status', type: 'text' },
];
export default class LeadManager extends LightningElement {
columns = COLUMNS;
company = '';
lastName = '';
isSaving = false;
wiredLeadsResult;
@wire(getOpenLeads)
wiredLeads(result) {
this.wiredLeadsResult = result;
}
get leads() {
return this.wiredLeadsResult?.data ?? [];
}
isFormValid() {
return [...this.template.querySelectorAll('lightning-input')]
.reduce((valid, field) => field.reportValidity() && valid, true);
}
async handleCreateLead() {
if (!this.isFormValid()) {
return;
}
this.isSaving = true;
try {
await createRecord({
apiName: LEAD_OBJECT.objectApiName,
fields: {
[COMPANY_FIELD.fieldApiName]: this.company,
[LAST_NAME_FIELD.fieldApiName]: this.lastName,
},
});
await refreshApex(this.wiredLeadsResult);
this.dispatchEvent(new ShowToastEvent({ title: 'Lead Created', variant: 'success' }));
} catch (error) {
this.dispatchEvent(new ShowToastEvent({
title: 'Could Not Create Lead',
message: error.body?.message ?? 'An unexpected error occurred.',
variant: 'error',
}));
} finally {
this.isSaving = false;
}
}
}
getOpenLeads follows Module 16's thin-Controller pattern; refreshApex(this.wiredLeadsResult) (Module 6) is what makes the newly created Lead appear in the datatable without a manual reload.
Exercise
Explain, as a comment, why refreshApex is needed after createRecord succeeds, even though createRecord itself already succeeded.
Show hint
Recall Module 6's reactive refresh lesson.
Exercise
Challenge: add a Phone field (not required) to the create form and its handler.
Show hint
Follow the same pattern as company/lastName.
Project: Lead Management Application 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 full Lead management feature — a searchable, sortable list plus a validated creation form — synthesizing Lightning Data Service (Module 6), datatables (Module 10), and forms (Module 8) into one realistic application.