Lightning Web Component

All Ways to Call Apex Method from LWC

One of the most powerful features of LWC is its ability to seamlessly integrate with Apex, Salesforce's server-side programming language. In this article, we will explore how to call Apex method from LWC, enabling you to discover the full power of Salesforce's backend functionality within your frontend components.

Call Apex method from LWC in Salesforce

Create the Apex

First, we need to create an Apex method that we want to call from our Lightning Web Component

public with sharing class MyApexController {
    
    @AuraEnabled(cacheable=true)
    public static String getGreetings(String name) {
        return 'Hello, ' + name + '!';
    }
}

When you mark an Apex method as cacheable, it means that the server response for that method will be cached on the client side (in the browser's memory) for a certain period of time. Subsequent calls to the same method with the same parameters will fetch the data from the local cache instead of making additional round trips to the server.

Here we'll show you some examples in how you can call Apex from LWC with parameters using different methods:

Wire service

In this approach, we're calling Apex class from LWC using wire decorator to call it declaratively. The @wire decorator is used to establish a wire adapter, which is responsible for fetching data from the server. The returned data is reactive, which means any changes in the data will automatically update the component's properties.

import { LightningElement, wire } from 'lwc';
import myApexMethod from '@salesforce/apex/MyApexController.myApexMethod';

export default class MyLWCComponent extends LightningElement {
    @wire(myApexMethod, { name: "John" })
    apexData({ error, data }) {
        if (data) {
            // Handle the data from Apex
            console.log(data);
        } else if (error) {
            // Handle any errors
            console.log(error);
        }
    }
}
Objects passed to a component are read-only. To mutate the data, a component should make a shallow copy of the objects it wants to mutate.

Imperative Apex

This method to call an Apex class is used when you need to perform operations when an event is triggered (ex. Button click) or in a specific section of the code.

<template>
    <lightning-button label="Call Apex Method" onclick={callApexMethod}></lightning-button>
</template>
import { LightningElement, wire } from 'lwc';
import getGreetings from '@salesforce/apex/MyApexController.getGreetings';

export default class MyComponent extends LightningElement {

    callApexMethod() {
        // Imperatively call the Apex method
        getGreetings({name: "John"})
            .then(result => {
                // Process the result from Apex
                console.log(result);
            })
            .catch(error => {
                // Handle any errors from the Apex call
                console.error(error);
            });
    }
}

When the button in the Lightning Web Component is clicked, the callApexMethod() function will be invoked, which in turn calls the Apex method getGreetings(). The result from the Apex method will be logged in the browser console, and any errors will be caught and logged as well.

Vlocity Invoke Service

You need to have Vlocity/Omnistudio installed in your organization to use this method. To check that go to Setup > Installed Packages. If you do not see the Vlocity Ins package, you can not use this method

Using this invoke service from vlocity, the apex class will suffer some modifications to be able to receive the data from the Lightning web component, this is how it should look like:

global without sharing class MyApexController implements vlocity_ins.VlocityOpenInterface{
    public Boolean invokeMethod(String methodName, Map<String,Object> inputMap, Map<String,Object> outputMap, Map<String,Object> options){
        if (methodName == 'getGreetings'){
            getGreetings(inputMap, outputMap);
        }
        return true;
    }
    
    public static String getGreetings(Map<String,Object> inputMap, Map<String,Object> outputMap) {
        Stirng name = (String)inputMap.get('name');
        return 'Hello, ' + name + '!';
    }
}

On the XML of the Lightning web component, you need to create a runtimeNamespace to invoke vlocity_ins

file_type_xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <isExposed>true</isExposed>
    <runtimeNamespace>vlocity_ins</runtimeNamespace>
</LightningComponentBundle>

On the Lightning web component you will not have to import the apex method, but you need to import OmniscriptBaseMixin from vlocity

import { OmniscriptBaseMixin } from 'vlocity_ins/omniscriptBaseMixin';

This method is imperative, meaning that it could be called on a user event (ex: OnClick). So to use this apex method on your Lightning web component you will need to call omniRemoteCall with your params. This will return a promise in which you can use .then to access the data received from the Apex class.

handleClick(){
    const input = { name: "John" }
    const params = {
        input: JSON.stringify(input),
        sClassName: 'MyApexController',
        sMethodName: 'getGreetings',
        options: '{}',
    };
    this.omniRemoteCall(params, true).then(response => {
        // Process the result from Apex
        console.log(response);
    })
    .catch(error => {
        // Handle any errors from the Apex call
        console.error(error);
    })
    .finally(() => {
        // optional: here you can execute a code when the call is finished 
    })
}