LWC – Lightning Input Forms with Dynamic Picklist Options

Lightning Web Components (LWC) provide a modern, efficient way to build powerful and interactive UI components in Salesforce. One of the most common requirements in Salesforce applications is handling input forms with dynamic picklist values.

In this guide, we’ll walk through:

  1. Fetching a record dynamically using Apex
  2. Creating an interactive input form in LWC
  3. Retrieving picklist values dynamically based on record type using ‘uiObjectInfoApi
  4. Implementing edit and save functionality with Apex updates

By the end of this tutorial, you’ll have a fully functional LWC form that allows users to edit and update Salesforce records with dynamic picklist fields. Let’s dive in!

Note: This component utilizes recordId as a public property. When placed on a Lead record detail page, it automatically retrieves the Lead Record for updates.

inputForms.html

<template>
    <lightning-card variant="Narrow">
        <div class="slds-m-around_medium">
            <div class="slds-grid slds-gutters">
                <div class="slds-col slds-size_1-of-2">
                    <lightning-input type="text" label="First Name" value={leadRecord.FirstName} data-field="FirstName"
                        onchange={handleInputChange} disabled={disableUpdate}>
                    </lightning-input>

                    <lightning-input type="text" label="Last Name" value={leadRecord.LastName} data-field="LastName"
                        onchange={handleInputChange} disabled={disableUpdate}>
                    </lightning-input>

                    <lightning-input type="email" label="Email" value={leadRecord.Email} data-field="Email"
                        onchange={handleInputChange} disabled={disableUpdate}>
                    </lightning-input>

                    <lightning-input type="phone" label="Phone" value={leadRecord.Phone} data-field="Phone"
                        onchange={handleInputChange} disabled={disableUpdate}>
                    </lightning-input>

                    <!-- <lightning-input type="text" label="Street" value={leadRecord.Street} data-field="Street"
                        onchange={handleInputChange} disabled={disableUpdate}>
                    </lightning-input> -->

                    <lightning-textarea label="Street" value={leadRecord.Street} data-field="Street"
                        onchange={handleInputChange} disabled={disableUpdate}></lightning-textarea>

                    <lightning-input type="text" label="City" value={leadRecord.City} data-field="City"
                        onchange={handleInputChange} disabled={disableUpdate}>
                    </lightning-input>

                    <lightning-input type="text" label="State" value={leadRecord.State} data-field="Email"
                        onchange={handleInputChange} disabled={disableUpdate}>
                    </lightning-input>

                    <lightning-input type="text" label="Country" value={leadRecord.Country} data-field="Country"
                        onchange={handleInputChange} disabled={disableUpdate}>
                    </lightning-input>

                    <lightning-combobox label="Status" value={leadRecord.Status} placeholder="Lead Status"
                        data-field="Status" options={statusOptions} onchange={handleInputChange}
                        disabled={disableUpdate}></lightning-combobox>

                    <lightning-input type="text" label="Nickname__c" value={leadRecord.Nickname__c}
                        data-field="Nickname__c" onchange={handleInputChange} disabled={disableUpdate}>
                    </lightning-input>
                    <div class="slds-p-top_medium slds-p-bottom_medium">
                        <template if:false={editMode}>
                            <lightning-button if:true={recordId} variant="brand" label="Edit Record"
                                onclick={handleEdit} class="slds-p-right_medium"></lightning-button>
                        </template>
                        <template if:true={editMode}>
                            <lightning-button if:true={recordId} variant="brand" label="Submit" onclick={handleSubmit}
                                class="slds-p-right_medium"></lightning-button>
                        </template>
                        <lightning-button variant="neutral" label="Cancel" onclick={handleCancel} disabled={hideCancel}>
                        </lightning-button>
                    </div>
                </div>
                <div class="slds-col slds-size_2-of-2">

                </div>
            </div>
        </div>
    </lightning-card>
</template>

inputForms.js

The handleInputChange method dynamically updates the leadRecord object whenever a user modifies an input field in the form. This feature enables seamless data binding between the form fields and the component’s JavaScript properties.

We use a wire method to dynamically fetch picklist values from the Lead object. To retrieve picklist values, obtaining the recordTypeId is necessary. Every object has a default recordTypeId if no specific Record Type is assigned. It can be obtained with the wire adapter getObjectInfo.

If you need to fetch the recordTypeId of a particular Record Type Names, you can use the getRecordTypeId method in the leadController Apex class by passing Object Name and RecordType Name as parameters.

import { LightningElement, wire, api, track } from 'lwc';
import { CurrentPageReference } from 'lightning/navigation'
import { getPicklistValues, getObjectInfo } from 'lightning/uiObjectInfoApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import getLeadRecord from '@salesforce/apex/leadController.getLeadRecord'
import updateLead from '@salesforce/apex/leadController.updateLead';
import LEAD_OBJECT from '@salesforce/schema/Lead';
import STATUS_FIELD from '@salesforce/schema/Lead.Status';

export default class InputForms extends LightningElement {
    //leadRecordId;
    @api recordId;
    leadRecord = {};
    @track statusOptions = [];
    recordTypeId;
    editMode = false;
    disableUpdate = true;
    hideCancel = true;

    // Get Object Info to retrieve default Record Type ID
    @wire(getObjectInfo, { objectApiName: LEAD_OBJECT })
    objectInfo({ data, error }) {
        if (data) {
            this.recordTypeId = data.defaultRecordTypeId;
            console.log('this.recordTypeId: ', this.recordTypeId);
        }
    }

    // Fetch Picklist Values
    @wire(getPicklistValues, { recordTypeId: '$recordTypeId', fieldApiName: STATUS_FIELD })
    wiredPicklistValues({ data, error }) {
        if (data) {
            this.statusOptions = data.values.map(option => ({
                label: option.label,
                value: option.value
            }));

            console.log('this.statusOptions: ', this.statusOptions);
        } else if (error) {
            console.error('Error fetching picklist values', error);
        }
    }


    connectedCallback() {
        this.editMode = false;
        // Manually get leadId from the URL if CurrentPageReference fails
        // this.leadRecordId = params.get('leadId');
        // console.log('Lead ID from URL:', this.leadRecordId);
    }

    /*
    @wire(CurrentPageReference)
    getStateParameters(currentPageReference) {
        if (currentPageReference) {
            this.leadRecordId = currentPageReference.state?.leadId;
            console.log('this.leadRecordId: ', this.leadRecordId);
        }
    }
    */

    @wire(getLeadRecord, { leadId: '$recordId' })
    wiredLead({ data, error }) {
        if (data) {
            console.log('Data: ', data);
            this.leadRecord = data;
            console.log('this.leadRecord: ', this.leadRecord);
        }
        else if (error) {
            console.error(error)
        }
    }

    handleInputChange(event) {
        const fieldName = event.target.dataset.field;
        const fieldValue = event.target.value;

        this.leadRecord = { ...this.leadRecord, [fieldName]: fieldValue };
        console.log('Field Change ', JSON.stringify(this.leadRecord));
    }

    handleSubmit() {
        updateLead({ leadRecord: this.leadRecord })
            .then((result) => {
                console.log('result ', result);
                this.enableEditMode(false);
                const event = new ShowToastEvent({
                    title: 'Success!',
                    message: 'Record Updated!',
                    variant: 'success'
                });
                this.dispatchEvent(event);
            }
            ).catch((err) => {
                console.error('Error updating lead:', JSON.stringify(err));
                console.error('err ', err.body?.message);
            })
    }

    handleEdit() {
        this.enableEditMode(true);
    }


    enableEditMode(state) {
        this.editMode = state;
        this.disableUpdate = !state;
        this.hideCancel = !state;
        console.log(`Edit Mode: ${state ? 'Enabled' : 'Disabled'}`);
    }

    handleCancel() {
        this.enableEditMode(false);
    }

}

leadController.apex

public class leadController {

    @AuraEnabled(cacheable=true)
    public static Lead getLeadRecord(Id leadId){
        return [SELECT Id,FirstName, LastName,Email,Phone,Street,City,State,Country, Status, Nickname__c FROM Lead WHERE Id=:leadId];
    }

    @AuraEnabled(cacheable=true)
    public static String getRecordTypeId(String objectApiName, String recordTypeName) {
        Map<String, Schema.RecordTypeInfo> recordTypes = Schema.getGlobalDescribe().get(objectApiName).getDescribe().getRecordTypeInfosByName();
        if (recordTypes.containsKey(recordTypeName)) {
            return recordTypes.get(recordTypeName).getRecordTypeId();
        }
        return null;
    }

    @AuraEnabled
    public static Lead updateLead(Lead leadRecord){
        if(leadRecord !=null){
            update leadRecord;
            System.debug('leadRecord: '+ leadRecord);
            return leadRecord;
        }
        else{
            return leadRecord;
        }
    }
}

Sample UI Screenshot:

Use the Edit Record Button to modify the lead details. Click Submit after the changes made.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses cookies to offer you a better browsing experience. By browsing this website, you agree to our use of cookies.