Call Apex Methods In Lightning web components
Let’s discuss here how to call the apex class from the Lightning web components. Lightning web components can import methods from Apex classes into the JavaScript classes using ES6 import.Before you use an Apex method, make sure that there isn’t an easier way to get the data. Before calling apex method first review a base Lightning component, like lightning-record-form, lightning-record-view-form, or lightning-record-edit-form works for your use case.
We can able to call the apex class in Lightning web component using these different ways.
For more information take a look here
Here some of highlights of this component.
- This component is used to display list of Accounts in picklist.
- The component is used to display list of Contacts related to respective Account. User can select Account Name from dropdown to see list of related contacts.
Here you go step by step Instructions to create the Lightning Web Component
Import Syntax
You can able use default export syntax to import an Apex method via the @salesforce/apex scoped module into JavaScript controller class. The Syntax looks like below.
import apexMethod from '@salesforce/apex/Namespace.Classname.apexMethod';
- apexMethod—The imported symbol that identifies the Apex method.
- Namespace—The namespace of the Salesforce organization. Specify a namespace unless the organization uses the default namespace (c), in which case don’t specify it.
- Classname—The name of the Apex class.
To use @wire
to call an Apex method, we must set cacheable=true
. But once we have used cacheable we cannot use DML in that. If an Apex method is annotated with @AuraEnabled(cacheable=true), you can invoke it from a component via the @wirewire service.You can @wire a property if you just wanna use the response as it is.
Create Apex Class
In this example, we will be getting account data and show it into the UI. Create an apex class using SFDX create apex class command.
public class AccountLWCController {
@AuraEnabled(cacheable=true)
public static List<Account> getAccountList() {
return [SELECT Id, Name FROM Account];
}
@AuraEnabled
public static List<Contact> getContacts(String accountId){
return [Select Id,FirstName,LastName,Email,Phone from Contact where accountId=:accountId];
}
}
Let’s build the AccountList LWC
Create a new Lightning web component using the below SFDX commandsfdx force:lightning:component:create --type lwc -n AccountList -d force-app/main/default/lwc
accountList.html
<template>
<lightning-card >
<div class="slds-page-header slds-page-header--object-home">
<lightning-layout>
<lightning-layout-item >
<lightning-icon icon-name="standard:contact" alternative-text="Contact" ></lightning-icon>
</lightning-layout-item>
<lightning-layout-item class="slds-m-left--small">
<p class="slds-text-title--caps slds-line-height--reset">Accounts</p>
<h1 class="slds-page-header__title slds-p-right--x-small">Contact
Viewer</h1>
</lightning-layout-item>
</lightning-layout>
<lightning-layout >
<lightning-layout-item >
<p class="slds-text-body--small"> Contacts • View
Contacts Based on Selected Account</p>
</lightning-layout-item>
</lightning-layout>
</div>
<label class="slds-form-element__label" for="select-01">Select Account</label>
<div class="slds-form-element__control">
<div class="slds-select_container">
<select class="slds-select" id="select-01" onchange={onValueSelection}>
<!--iterate all picklist values from accounts list using for:each loop-->
<template for:each={accounts.data} for:item="acc">
<option key={acc.Id} value={acc.Id}>
{acc.Name}
</option>
</template>
</select>
</div>
</div>
<template if:true={contacts}>
<lightning-card title="Contacts" >
<div style="height: 300px;">
<lightning-datatable
key-field="Id"
data={contacts}
columns={columns}>
</lightning-datatable>
</div>
</lightning-card>
</template>
</lightning-card>
</template>
accountList.js
The component’s JavaScript code imports the Apex method.On selection of picklist onValueSelection get triggered and call the getContacts() method with accountId parameter. Once getContacts() get called it gives the response as Promise and will handle that using .then() and .catch() properties.
import { LightningElement,wire,track } from 'lwc';
import getAccountList from '@salesforce/apex/AccountLWCController.getAccountList';
import getContacts from '@salesforce/apex/AccountLWCController.getContacts';
const columns = [{
label: 'First Name',
fieldName: 'FirstName'
},
{
label: 'Last Name',
fieldName: 'LastName'
},
{
label: 'Email',
fieldName: 'Email',
type: 'email'
},
{
label: 'Phone',
fieldName: 'phone',
type: 'phone'
}
];
export default class AccountList extends LightningElement {
@track accountId = '';
@track contacts;
@track columns = columns;
// invoke apex method with wire property and fetch picklist options.
// pass 'object information' and 'picklist field API name' method params which we need to fetch from apex
@wire(getAccountList) accounts;
onValueSelection(event) {
// eslint-disable-next-line no-alert
const selectedAccount = event.target.value;
this.accountId = event.target.value;
if (selectedAccount != null) {
getContacts({
accountId: selectedAccount
})
.then(result => {
this.contacts = result;
// eslint-disable-next-line no-console
console.log('result' + JSON.stringify(result) + selectedAccount);
})
.catch(error => {
this.error = error;
});
}
}
}
accountList.js-meta.xml
To make sure component is visible in Lightning App Builder you need to add targets and change isExposed to true in LightningDatatableExample.js-meta.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>47.0</apiVersion>
<isExposed>true</isExposed>
<masterLabel>Account List</masterLabel>
<description>This is a demo component.</description>
<targets>
<target>lightning__RecordPage</target>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>
Below is the output of component.
References: