top of page
  • Writer's pictureS. Chaudhary

Insert Multiple Records Using LWC

Are you a Salesforce developer looking to drastically reduce the time and effort required to insert multiple records? Discover the transformative approach offered by Salesforce Lightning Web Components (LWC). In our latest blog post, we dive deep into a common yet pivotal challenge faced by developers: the efficient insertion of numerous records into the Salesforce ecosystem in one fell swoop. Whether it's adding a list of contacts, opportunities, or custom objects, the traditional one-at-a-time method is not only cumbersome but a significant productivity killer.


Salesforce Lightning Web Components (LWC) offers a robust framework for building interactive user interfaces within the Salesforce ecosystem. One common requirement in many applications is the ability to insert multiple records in a single DML, whether it's adding multiple contacts, opportunities, or custom objects. In this blog post, we'll explore how to achieve this functionality using LWC on the Account object.


Understanding the Requirement

Imagine you're tasked with developing a Salesforce application where users must add multiple accounts in one go. Traditionally, users would have to input each account individually, which can be time-consuming. Our goal is to enhance this process by allowing users to add multiple accounts at once, significantly improving productivity.


This can be easily done by using LDS (Lightning-record-edit-form). However, the issue with Lightning-record-edit-form is that it will call the server side as many times as the records we want to insert. For example, if we want to insert 5 records, it will call the server 5 times and then perform 5 DML statements. This blog will help to insert a list of records with a single DML statement.

Implementing the Solution

We need to create one LWC component and its apex controller classes to achieve this functionality.


Step -1:- Create 4 Apex classes to handle backend Functionality:-


  1. InsertMultipleRecordController 

  2. InsertMultipleAccountWrapper 

  3. AccountProcessor

  4. AccountDomain


InsertMultipleRecordController.cls 
public with sharing class InsertMultipleRecordController {
   @AuraEnabled
   public static void insertMultipleAccountRecord(String accounts){
      try {
         List<InsertMultipleAccountWrapper> accountsToInsert = 
            (List<InsertMultipleAccountWrapper>)JSON.deserialize(
              accounts,
              List<InsertMultipleAccountWrapper>.class
         );
         AccountProcessor.processMultipleAccountToInsert(accountsToInsert);
      }
      catch (Exception e) {
         throw new AuraHandledException(e.getMessage());
      }
   } 
}
InsertMultipleAccountWrapper.cls 
public with sharing class InsertMultipleAccountWrapper {
    @AuraEnabled
    public String accountName;
    @AuraEnabled
    public String accountPhone;
    @AuraEnabled
    public String accountNumber;
    public InsertMultipleAccountWrapper(
        String accountName,
        String accountPhone,
        String accountNumber
    ) {
        this.accountName = accountName;
        this.accountNumber = accountNumber;
        this.accountPhone = accountPhone;
    }
}
AccountProcessor.cls
public with sharing class AccountProcessor {
    /**
    * This method aims to insert multiple Account
    * @param Account name
    * @param Account phone
    * @param Account number
    * @return N/A
    */
    public static void processMultipleAccountToInsert(
        List<InsertMultipleAccountWrapper> accounts
    ) {
        List<Account> accountsToInsert = new List<Account>();
        for (InsertMultipleAccountWrapper account : accounts) {
            accountsToInsert.add(new Account(
                Name = account.accountName,
                Phone = account.accountPhone,
                AccountNumber = account.accountNumber
            ));
        }
        AccountDomain.insertAccounts(accountsToInsert);
    }
}
AccountDomain.cls
public class AccountDomain {
    /**
    * This method aims to insert Account record
    * @param List<Account>
    * @return N/A
    */
    public static void insertAccounts(List<Account> accounts) {
        try {
            insert accounts;
        }
        catch (Exception e) {
            throw e;
        }
    }
}

Step 2:- Create LWC component InsertMultipleRecord


InsertMultipleRecord.js
import {LightningElement, track} from 'lwc';
import {ShowToastEvent} from 'lightning/platformShowToastEvent';
import ERROR from "@salesforce/label/c.ERROR";
import SUCCESS from "@salesforce/label/c.Custom_Success_Title_Label";
import ACCOUNT_NAME_REQUIRED from "@salesforce/label/c.ACCOUNT_NAME_REQUIRED";
import ACCOUNT_NAME from "@salesforce/label/c.ACCOUNT_NAME";
import ACCOUNT_PHONE from "@salesforce/label/c.ACCOUNT_PHONE";
import ACCOUNT_NUMBER from "@salesforce/label/c.ACCOUNT_NUMBER";
import ACCOUNTS_INSERTED from "@salesforce/label/c.ACCOUNTS_INSERTED";
import CREATE_ACCOUNTS from "@salesforce/label/c.CREATE_ACCOUNTS";
import insertMultipleAccountRecord from "@salesforce/apex/InsertMultipleRecordController.insertMultipleAccountRecord";
import {NavigationMixin} from 'lightning/navigation';

export default class InsertMultipleRecord extends NavigationMixin(LightningElement) {
    @track accountsToCreate = [];
    label = {
        ERROR: ERROR,
        SUCCESS: SUCCESS,
        ACCOUNT_NAME_REQUIRED: ACCOUNT_NAME_REQUIRED,
        ACCOUNT_NAME: ACCOUNT_NAME,
        ACCOUNT_PHONE: ACCOUNT_PHONE,
        ACCOUNT_NUMBER: ACCOUNT_NUMBER,
        ACCOUNTS_INSERTED: ACCOUNTS_INSERTED,
        CREATE_ACCOUNTS: CREATE_ACCOUNTS
    }
    recordCount = 0;
    saveButtonLabel;

    connectedCallback() {
        this.addRow();
    }

    addRow(event) {
        this.accountsToCreate.push(this.initialNewRecord());
        this.saveButtonLabel = `Save Records (${this.accountsToCreate.length})`;
    }

    handleAddRow(event) {
        let index = parseInt(event.target.dataset.index);
        if (
            this.accountsToCreate[index].accountName == "" ||
            !this.accountsToCreate[index].accountName
        ) {
            let rowNo = index + 1;
            this.showToastEvent(
                this.label.ERROR,
                `${this.label.ACCOUNT_NAME_REQUIRED} ${rowNo}`,
                this.label.ERROR
            )
            return;  
        }
        this.accountsToCreate[index].showAddButton = false;
        this.accountsToCreate[index].showDeleteButton = true;
        this.addRow(event);
        this.accountsToCreate[index + 1].showDeleteButton = true;

    }

    handleDeleteRow(event) {
        if (this.accountsToCreate.length > 1) {
            let index = event.target.dataset.index
            if (index == this.accountsToCreate.length - 1) {
                this.accountsToCreate[index - 1].showAddButton = true;
            }
            this.accountsToCreate.splice(index, 1);
        }
        if (this.accountsToCreate.length == 1) {
            this.accountsToCreate[0].showDeleteButton = false;
        }
        this.saveButtonLabel = `Save Records (${this.accountsToCreate.length})`;
    }

    handleChange(event) {
        this.accountsToCreate[event.target.dataset.index][event.target.name] =
            event.target.value;
    }

    handleSave(event) {
        for (let index in this.accountsToCreate) {
            if (
                this.accountsToCreate[index].accountName == '' ||
                !this.accountsToCreate[index].accountName
            ) {
                let rowNo = parseInt(index) + 1;
                this.showToastEvent(
                    this.label.ERROR,
                    `${this.label.ACCOUNT_NAME_REQUIRED} ${rowNo}`,
                    this.label.ERROR
                )
                return;
            }
        }
        this.insertRecords();
    }

    insertRecords() {
        insertMultipleAccountRecord({ accounts: JSON.stringify(this.accountsToCreate) })
            .then((result) => {
                this.showToastEvent(this.label.SUCCESS, this.label.ACCOUNTS_INSERTED, this.label.SUCCESS);
                this[NavigationMixin.Navigate]({
                    type: "standard__objectPage",
                    attributes: {
                        objectApiName: "Account",
                        actionName: "list",
                    },
                    state: {
                        filterName: "Recent"
                    },
                });
            })
            .catch((error) => {
                this.showToastEvent(this.label.ERROR, error.body.errorMessage, this.label.ERROR);
            })
    }

    initialNewRecord() {
        return ({
            accountName: '',
            accountPhone: '',
            accountNumber: '',
            showAddButton: true,
            showDeleteButton: false
        });
    }

    showToastEvent(title, message, variant) {
        this.dispatchEvent(
            new ShowToastEvent({
                title: title,
                message: message,
                variant: variant
            })
        );
    }
}
InsertMultipleRecord.html
<template>
    <lightning-card icon-name="standard:account" variant="base" title={label.CREATE_ACCOUNTS}>
        <template for:each={accountsToCreate} for:item="record" for:index="index">
            <div key={record} class="slds-grid slds-gutters_small">
                <div class="slds-col slds-side_3-of-12">
                    <lightning-input label={label.ACCOUNT_NAME} name="accountName" data-index={index} onchange={handleChange}
                        value={record.accountName} required></lightning-input>
                </div>
                <div class="slds-col slds-side_3-of-12">
                    <lightning-input label={label.ACCOUNT_PHONE} name="accountPhone" data-index={index}
                        onchange={handleChange} value={record.accountPhone}>
                    </lightning-input>
                </div>
                <div class="slds-col slds-side_3-of-12">
                    <lightning-input label={label.ACCOUNT_NUMBER} name="accountNumber" data-index={index}
                        onchange={handleChange} value={record.accountNumber}></lightning-input>
                </div>
                <div class="slds-col slds-side_3-of-12" style="text-align:center; margin-top: auto; width: 55px;">
                    <template if:true={record.showAddButton}>
                        <lightning-icon style="cursor: pointer;" data-index={index}
                            variant="brand" icon-name="utility:new" onclick={handleAddRow}>
                        </lightning-icon>
                    </template>
                    <template if:true={record.showDeleteButton}>
                        <lightning-icon data-index={index} icon-name="action:delete" style="cursor: pointer;"
                            size="x-small" onclick={handleDeleteRow}>
                        </lightning-icon>
                    </template>
                </div>
            </div>
        </template>
        <div style="text-align: center; margin: 7px;">
            <lightning-button variant="brand" label={saveButtonLabel} onclick={handleSave}>
            </lightning-button>
        </div>
    </lightning-card>
</template>
InsertMultipleRecord.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>59.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

Step 3:- After creating the LWC component and all its related classes, embed the InsertMultipleRecord LWC component onto your desired page. In our case, we have used it on the Record Page. You can use it according to your requirements.


Now, you can insert multiple account records. You just need to click on the + button, fill in the row data, and then click the Save Record button. It will insert all the records and redirect you to the Account list view page.


Conclusion

In conclusion, Salesforce Lightning Web Components (LWC) enable efficient insertion of multiple records in a single operation. By implementing this feature on the Account object, users can add multiple accounts simultaneously, improving productivity and streamlining workflow. This demonstrates the flexibility and power of LWC in enhancing Salesforce applications to meet user needs effectively.


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.


Thank You! You can leave a comment to help me understand how the blog helped you. If you need further assistance, please contact us. You can click "Reach Us" on the website and share the issue with me.


Reference



Blog Credit:

S. Chaudhary

   Salesforce Developer

   Avenoir Technologies Pvt. Ltd.

  Reach us: team@avenoir.ai

Recent Posts

See All
bottom of page