top of page
Search
Shreyas Dhond

Simple Account creation Wizard using Lightning Web Components

Updated: Jan 14

Lightning Web Components (LWC) is Salesforce's implementation of a framework built on top of web standards. Web standards provides a common component model, programming model, interoperable components, better performance. The better performance is a result of the core features (component and programming model) implemented natively in the javascript engine, instead of in framework abstractions.



LWC provides a layer of specialized Salesforce services on top of the core stack, including base lightning components for scaffolding, lightning data service (lds) for easy access to salesforce data apis, and the user interface api that makes the base lighting components and the the lds metadata aware. Overall lightning web components allows Salesforce developers to work with a cutting-edge programming model that is built for the 2019 web stack with backwards interoperatability.



Resources

There are multiple resources provided by Salesforce that will help you get started. Personally I found the recipes collection to be really useful in learning the basic mechanisms that can be chained and enhanced. The dev guide is also really useful to learn the nitty gritty such as lifecycle hooks, event propagation, configuration targets, decorators etc.


Simple Account Creation Wizard



In order to get some familiarity with lwc, I decided to built a simple wizard without an apex side code. The wizard consists of four components. A container component (CustomAccountWizard), component to get account details (accountDetails), component to get contact details (contactDetails), and a review component (customAccountWizardReview). The diagram below shows the component composition.




The child components bubble events to change the status of the wizard and the container component manages the state and renders the child components. The code for all the components can be found in the following repository [lwc-customaccountwizard]. Below I have highlighted a few code snippets that I think make lightning web components a clear upgrade to lightning components.


Events 

The following points make the event framework an upgrade from previous lightning components.


  • Custom events do not need to be defined in a separate construct and can be created dynamically.

  • Events dispatched using the dispatchEvent method extended from LightningElement.

  • Parameters can be added with ease and the complexity of the parameters is limitless. 


contactDetails.js

import { LightningElement } from 'lwc';
import CONTACT_OBJECT from '@salesforce/schema/Contact';

export default class ContactDetails extends LightningElement {
    handleSubmit(event) {
        event.preventDefault(); //stop default action

        //Send event to parent to go to next page
        let fields = event.detail.fields;
        fields.AccountId = '';
        let recordInput = { allowSaveOnDuplicate: true, apiName: CONTACT_OBJECT.objectApiName, fields };
        this.dispatchEvent(new CustomEvent('next', {detail: recordInput}));
    }

    handlePrevious(event) {
        event.preventDefault(); //stop default action

        //Send event to parent to go to next page
        let fields = event.detail.fields;
        fields.AccountId = '';
        let recordInput = { allowSaveOnDuplicate: true, apiName: CONTACT_OBJECT.objectApiName, fields };
        this.dispatchEvent(new CustomEvent('previous', {detail: recordInput}));
    }
}

  • Parents can register for events on child components in their declaration in the markup.


CustomAccountWizard.js (snippet)

<template id="contactDetailsDiv" if:true={showContactDetailsForm}>
    <c-contact-details onprevious={handlePrevious} onnext={handleNext}></c-contact-details>
</template>

** Caveat: In some (many probably) cases you would want to communicate between sibling components that are not part of the same DOM. In that case a publish-subscribe service can be used or developed. There is one available in the lwc-recipes that can be plugged into a solution and used as a service.


Utility Code and Reusability

In the aura lightning framework utility code had to be included in a static resource or another component and had to be included in the consuming components markup. For external libraries included through static resources, they cannot be accessed in components init functions and can only be used after the afterscriptsloaded callback executes.


Lightning Data Service

Lightning Data Service is much improved in lighting web components and can function from the service can be easily imported and used without being included in component markup. In the below code chain creation of account and contact would be possible in lightning components but the lightning data service for account and contact would have to be included in the component markup and would have be accessed using dom selectors. The below code is much cleaner and easier to follow and implement.

customAccountWizardReview.js


import { LightningElement, api } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { createRecord } from 'lightning/uiRecordApi';

export default class CustomAccountWizardReview extends LightningElement {
    @api contact;
    @api account;

    handleSubmit() {
        let accountToCreate = this.account;

        //Create Account and get Id
        createRecord(accountToCreate).then(account => {
            console.log('account: ' + JSON.stringify(account));
            let accountId = account.id; //this took some finding

            //Create Contact and parent with Account Id
            const fields = {};
            Object.assign(fields, this.contact.fields);
            fields.AccountId = accountId;

            let contactToCreate = { allowSaveOnDuplicate: true, apiName: 'Contact', fields };
            console.log('contactToCreate: ' + JSON.stringify(contactToCreate));
            //createContact
            createRecord(contactToCreate).then(contact => {
                let contactId = contact.id;
                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Success',
                        message: 'Account and Contact created successfully!',
                        variant: 'success',
                    }),
                );

                //Send Event to navigate
                let detail = {};
                detail.accountId = accountId;
                detail.contactId = contactId;
                this.dispatchEvent(
                    new CustomEvent('submit', {detail: detail})
                );
            }).catch(error => {
                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Error creating contact',
                        message: error.message,
                        variant: 'error',
                    }),
                );
            });
        })
        .catch(error => { 
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error creating account',
                    message: error.message,
                    variant: 'error',
                }),
            );
        });
    }

    handlePrevious() {
        //Send event to parent to go to next page
        this.dispatchEvent(new CustomEvent('previous'));
    }
}

8 views0 comments

Comments


bottom of page