In this blog post, I'll walk you through the code for creating a Multi-Step Lightning Record Form using Lightning Web Components (LWC) in Salesforce. In other words, I will let you know how to create an LWC component path similar to an Opportunity or Lead path. This code allows users to easily create and manage related records, such as an Account, Contact, and Opportunity, in a structured and guided manner.
Preview
Component Structure
Frontend
This component displays a progress path to indicate the current step in the multi-step process. Users can select a step in the path to navigate to a specific part of the form.
These sections represent the steps for creating different records: Account, Contact, and Opportunity. The lightning-record-form component is used to create these records. It allows users to input data, and the onsuccess attribute specifies a method to handle successful record creation.
These buttons enable users to navigate through the form. The "Next" button advances to the next step, while the "Previous" button goes back to the previous step. These buttons are conditionally rendered based on the current step.
sfParent.html
<template>
<lightning-card>
<div class="slds-p-horizontal large">
<c-sf-lightning-path current-state={currentPath} steps={pathItems}
onselectedpath={selectedpath}></c-sf-lightning-path>
</div>
<!-- Create Account-->
<div if:true={isStep1}>
<lightning-record-form object-api-name={Account} layout-type="Compact" columns="2" onsuccess={handleSuccess}>
</lightning-record-form>
</div>
<!-- Create Contact-->
<div if:true={isStep2}>
<lightning-record-form object-api-name={Contact} layout-type="Compact" columns="2">
</lightning-record-form>
</div>
<!-- Create Opportunity-->
<div if:true={isStep3}>
<lightning-record-form object-api-name={Opportunity} layout-type="Compact" columns="2" onsuccess={handleSuccessOppo}>
</lightning-record-form>
</div>
<div slot="footer" class="slds-clearfix">
<template if:false={isStep3}>
<lightning-button class="button slds-m-horizontal_x-small slds-float_right" slot="actions"
variant="brand" label={label.NEXT} title={label.NEXT} onclick={nextHandler}></lightning-button>
</template>
<template if:false={isStep1}>
<lightning-button class=" button slds-m-horizontal_x-small slds-float_right" slot="actions"
variant="brand" label={label.PREVIOUS} title={label.PREVIOUS} onclick={backHandler}></lightning-button>
</template>
</div>
</lightning-card>
</template>
Backend
Let's briefly understand the JavaScript logic in the sfParent.js file:
step: This variable keeps track of the current step in the multi-step process.
pathItems and pathElements: These variables store the path data for the progress indicator.
handleChangePath(event): This method is called when a step in the path is selected, updating the current step.
backHandler(event) and nextHandler(event): These methods allow users to navigate back and forth between steps by updating the step variable.
handleSuccess(event): This method is triggered when the Account record is successfully created. It captures the Account's ID.
handleSuccessOppo(): This method displays a success message and navigates to the newly created Account's detail page after the Opportunity record is successfully created.
navigateToViewAccountPage(recordId): This method uses Salesforce NavigationMixin to redirect to the Account detail page based on the captured Account ID.
sfParent.js
import {LightningElement, api} from 'lwc';
import {pathItems, pathElements} from 'c/paths';
import accountAPIName from '@salesforce/schema/Account';
import contactAPIName from '@salesforce/schema/Contact';
import opportunityAPIName from '@salesforce/schema/Opportunity';
import {ShowToastEvent} from 'lightning/platformShowToastEvent';
import {NavigationMixin} from 'lightning/navigation';
import REGISTRATION_COMPLETED from "@salesforce/label/c.REGISTRATION_COMPLETED";
import REGISTRATION_COMPLETED_MESSAGE from "@salesforce/label/c.REGISTRATION_COMPLETED_MESSAGE";
import NEXT from "@salesforce/label/c.NEXT";
import PREVIOUS from "@salesforce/label/c.PREVIOUS";
export default class SfParent extends NavigationMixin(LightningElement) {
step = 1;
pathItems = pathItems;
pathElements = pathElements;
currentPath = pathElements[0];
Account = accountAPIName;
Contact = contactAPIName;
Opportunity = opportunityAPIName;
accountId;
label = {
NEXT : NEXT,
PREVIOUS : PREVIOUS,
REGISTRATION_COMPLETED : REGISTRATION_COMPLETED,
REGISTRATION_COMPLETED_MESSAGE : REGISTRATION_COMPLETED_MESSAGE
}
get isStep1(){
return this.step === 1
}
get isStep2(){
return this.step === 2
}
get isStep3(){
return this.step === 3
}
handleChangePath(event){
this.step = event.detail;
this.currentPath = this.pathElements[this.step];
}
backHandler(event){
this.step = this.step-1;
this.currentPath = this.pathElements[this.step-1];
}
nextHandler(event){
this.step = this.step+1;
this.currentPath = this.pathElements[this.step-1];
}
handleSuccess(event){
this.accountId = event.detail.id;
}
handleSuccessOppo(){
const evt = new ShowToastEvent({
title : REGISTRATION_COMPLETED,
message : REGISTRATION_COMPLETED_MESSAGE,
variant : 'success',
});
this.dispatchEvent(evt);
this.navigateToViewAccountPage(this.accountId);
}
navigateToViewAccountPage(recordId) {
this[NavigationMixin.Navigate]({
type : 'standard__recordPage',
attributes : {
recordId: recordId,
objectApiName : 'Account',
actionName : 'view'
},
});
}
}
sfParent.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>58.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__Tab</target>
</targets>
</LightningComponentBundle>
Progress Indicator
Frontend
sfLightningPath.html
<template>
<div class="slds-readonly-path">
<lightning-progress-indicator current-step={currentState} type="path" variant="brand">
<template for:each={steps} for:item="step">
<lightning-progress-step label={step.label} value={step.value} key={step.label} onclick={pathHandler}></lightning-progress-step>
</template>
</lightning-progress-indicator>
</div>
</template>
Creating a progress indicator with a series of steps displayed as a path. The lightning-progress-indicator component is used, with the currentState property determining the current step in the indicator. It iterates over a list of steps defined in the steps array and displays each step using the lightning-progress-step component. The label and value attributes of each step are populated from the steps array, and a click event is linked to a function called pathHandler to handle user interactions.
Backend
sfLightningPath.js
import {LightningElement, api} from 'lwc';
import {pathItems, pathElements} from 'c/paths';
export default class SfLightningPath extends LightningElement {
@api currentState = '';
@api steps;
@api currentStepIndex;
pathElements = pathElements;
pathHandler(event) {
if(this.pathElements.indexOf(this.currentState)>this.pathElements.indexOf(event.currentTarget.value)) {
this.currentState = event.currentTarget.value;
this.dispatchEvent(new CustomEvent('selectedpath', {
detail : this.currentState
}));
}
}
}
sfLightningPath.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>58.0</apiVersion>
<isExposed>false</isExposed>
</LightningComponentBundle>
paths.js
const pathItems = [
{ label : 'Create Account', value : 'accountComponent', visible : false },
{ label : 'Create Contact', value : 'contactComponent', visible : false },
{ label : 'Create Opportunity', value : 'opportunityComponent', visible : false }
];
const pathElements = ['accountComponent', 'contactComponent', 'opportunityComponent'];
export{pathItems, pathElements};
This code defines two arrays, pathItems and pathElements, which are used to manage the visibility and values of elements in a multi-step process. The pathItems array contains objects representing steps in the process, with labels, values, and an initial visibility state set to false. The pathElements array contains values that correspond to steps, allowing for easy reference and management of their visibility. These arrays can be exported for use in other parts of the application, providing a structured way to control and display steps in a sequential process.
paths.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>58.0</apiVersion>
<isExposed>false</isExposed>
</LightningComponentBundle>
Development Result
Account Page
After saving data using the “Save button”
After clicking on the next button you will be redirected to the Contact page
The same goes for the opportunity page
Opportunity page
After filling out the opportunity page you will be redirected to the Account record page that you created.
Conclusion
In conclusion, this blog has demonstrated how to create a Multi-Step Lightning Record Form in Salesforce using Lightning Web Components (LWC). This development enhances the efficiency and data accuracy of related record creation by guiding users through a structured and intuitive process. It's a valuable addition to Salesforce customization, making it easier for users to manage their data.
If you'd like to see the code and resources used in this project, you can access the repository on GitHub.To access the AVENOIRBLOGS repository, click here. Feel free to explore the code and use it as a reference for your projects.
Happy Coding! Please leave a comment to help me understand how the blog helped you. If you need further assistance, please contact us. You can also click "Reach Us" on the website and share the issue with me.
Reference
https://www.avenoir.ai/post/real-time-preview-for-lightning-web-components
https://www.avenoir.ai/post/new-salesforce-cli-commands-for-better-deployment-control
lightning-progress-indicator - example - Salesforce Lightning Component Library
lightning-record-form - documentation - Salesforce Lightning Component Library
Blog Credit:
S. Chaudhary
Salesforce Developer
Avenoir Technologies Pvt. Ltd.
Reach us: team@avenoir.ai
Comentários