The main concept included in this recipe is invoking an Apex method imperatively. Don’t get confused by the term, it is used meaning that the function to retrieve the contacts is executed when the user presses the button, and it is not managed by the Salesforce LDS.
This use case is adequate when you don’t want to call the function when the component is loaded but on the click of a button, or certain logic occurs in your project.
<aside>
📂 Find this LWC in this folder: force-app\\main\\default\\lwc\\apexImperativeMethod\\apexImperativeMethod
</aside>
Inside the ContactController
class, the method getContactList
is exposed using the @AuraEnabled(cacheable=true)
decorator, this is required to be able to call this method from LWC.
This method returns a maximum of 10 Contact
records with a picture attached:
public with sharing class ContactController {
@AuraEnabled(cacheable=true) //Exposing the Method to LWC
public static List<Contact> getContactList() {
return [
SELECT
Id, Name, FirstName, LastName, Title, Phone, Email, Picture__c
FROM Contact
WHERE Picture__c != NULL
WITH SECURITY_ENFORCED
LIMIT 10
];
}
...
The template provides a button to load the contacts as a user action. The action is triggering the handleLoad
Javascript handler.
Once the handler has been executed, if the contacts
variable contains any value, it is iterated to show some contact values.
...
<div class="slds-var-m-around_medium">
<p class="slds-var-m-bottom_small">
<lightning-button
label="Load Contacts"
**onclick={handleLoad}**
></lightning-button>
</p>
<template lwc:if={contacts}>
<template for:each={contacts} for:item="contact">
<p key={contact.Id}>{contact.Name}</p>
</template>
</template>
<template lwc:elseif={error}>
<c-error-panel errors={error}></c-error-panel>
</template>
</div>
...
In order to use this method in the LWC, an import
is required in the Javascript.
Apart from importing the reference to the Apex method, the handleLoad
handler needs to be implemented.
The execution of the Apex method is managed in an asynchronous environment, so when the call is executed, the single response is a Javascript promise.
Prior to Spring ‘24 the try/catch
approach was used, but the newer and more clear async/await
approach is taken:
import { LightningElement } from 'lwc';
import getContactList from '@salesforce/apex/ContactController.getContactList';
export default class ApexImperativeMethod extends LightningElement {
contacts;
error;
async handleLoad() {
try {
this.contacts = await getContactList();
this.error = undefined;
} catch (error) {
this.contacts = undefined;
this.error = error;
}
}
handleLoadPreviousToSpring24() {
getContactList()
.then((result) => {
this.contacts = result;
this.error = undefined;
})
.catch((error) => {
this.error = error;
this.contacts = undefined;
});
}
}