Lightning Web Component

How to Update Record in LWC using Apex

As a Salesforce developer, you're probably familiar with the power of Lightning Web Components (LWC) and the capabilities of Apex Salesforce's programming language.

In this article, we'll explore a common task: how to update record in lwc using Apex. We'll show you a basic and easy example to understand.

How to Update Record in LWC using Apex

Create the Apex Controller

First, create the Apex controller to handle the record to get updated. For this example, we'll retrieve the record and then update it.

Let's declare two methods here: getAccounts will retrieve the accounts into our LWC, and saveAccounts will save them after editing.

public with sharing class AccountsController {

    @AuraEnabled(cacheable=true)
    public static List<Account> getAccounts() {
        return [SELECT Id, 
                    Name, 
                    Industry, 
                    RequestDate__c, 
                    IsActive__c 
                FROM Account ORDER BY CreatedDate DESC LIMIT 10]; 
    }

    @AuraEnabled
    public static void saveAccounts(List<Account> inputAccs) {
        update inputAccs;
    }
}

Create the Lightning Web Component

Once the Apex controller is ready, you can create the component showing the record on the UI.

In this scenario, we will create lightning-input components to display various fields from the Account object and a lightning-button component to save any changes made.

<template>
    <lightning-button label="Save Data" onclick={handleSave}>
    </lightning-button>

    <template if:true={accounts.data} for:each={accounts.data} for:item="acc">
        <lightning-card key={acc.Id} variant="Narrow" title="Account" icon-name="standard:account">
            <lightning-input type="text" label="Name" data-id={acc.Id} data-field="Name" onchange={handleOnChange} value={acc.Name}>
            </lightning-input>
            <lightning-input type="date" label="Request Date" data-id={acc.Id} data-field="RequestDate__c" onchange={handleOnChange} value={acc.RequestDate__c}>
            </lightning-input>
            <lightning-input type="checkbox" label="Active" data-id={acc.Id} data-field="IsActive__c" onchange={handleOnChange} checked={acc.IsActive__c}>
            </lightning-input>
        </lightning-card>
    </template>
</template>
You must include the exact field API Name on the data-field property, allowing us to get the values dynamically later.

Make imports

To call both Apex methods in the Javascript of your component, you need to use the wire property. If you want to include a message, use the ShowToastEvent. Additionally, you can use the refreshApex method to refresh the data once it has been saved.

import { LightningElement, wire } from 'lwc';
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import { refreshApex } from "@salesforce/apex";

import getAccounts from "@salesforce/apex/AccountsController.getAccounts";
import saveAccounts from "@salesforce/apex/AccountsController.saveAccounts";

export default class ChildComponent extends LightningElement {
    @wire(getAccounts)
    accounts;

}

Handle account data

First, you must complete a function handleOnChange, that will run every time a user changes the fields. Within that function, you should declare some constants to obtain the properties that the user is modifying. Once you have these values, you can update the account.data with the latest information.

import { LightningElement, wire } from 'lwc';
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import { refreshApex } from "@salesforce/apex";

import getAccounts from "@salesforce/apex/AccountsController.getAccounts";
import saveAccounts from "@salesforce/apex/AccountsController.saveAccounts";

export default class ChildComponent extends LightningElement {
    @wire(getAccounts)
    accounts;

    handleOnChange(e){
        const field = e.currentTarget.dataset.field;
        const recordId = e.currentTarget.dataset.id;
        const value = e.detail.value;
        const check = e.target.checked;

        this.accounts.data = this.accounts.data.map(item => {
            if(item.Id !== recordId) return item;
            if(e.target.type == 'checkbox') return {...item, [field]: check}

            return {...item, [field]: value}
        })
    }
}

Update records using Apex

Finally, here is where we update the records using Apex. Use the function you declared on the lightning-button to call the Apex method to save the accounts.

import { LightningElement, wire } from 'lwc';
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import { refreshApex } from "@salesforce/apex";

import getAccounts from "@salesforce/apex/AccountsController.getAccounts";
import saveAccounts from "@salesforce/apex/AccountsController.saveAccounts";

export default class ChildComponent extends LightningElement {
    @wire(getAccounts)
    accounts;

    handleOnChange(e){
        const field = e.currentTarget.dataset.field;
        const recordId = e.currentTarget.dataset.id;
        const value = e.detail.value;
        const check = e.target.checked;

        this.accounts.data = this.accounts.data.map(item => {
            if(item.Id !== recordId) return item;
            if(e.target.type == 'checkbox') return {...item, [field]: check}

            return {...item, [field]: value}
        })
    }

    handleSave(){
        saveAccounts({inputAccs: this.accounts.data})
        .then(() => {
            this.showMessage('Success', 'Accounts has been updated!', 'success');
            refreshApex(this.accounts)
        })
        .catch(error => {
            this.showMessage('Error', error.body.message, 'error');
        });
    }

    showMessage(title, message, variant){
        this.dispatchEvent(
            new ShowToastEvent({
            title: title,
            message: message,
            variant: variant,
            }),
        );
    }
}
Use the same parameter name as you have on your Apex controller, in this case is: inputAccs

Here is the final result of our component:

How to Update Record in LWC using Apex