Hello Friends, in this chapter, we will learn how to access Salesforce Data in Lightning Web Component and then how to access data using apex.
Topics Covered:
- Ways to Access Salesforce Data in LWC
- How to Use Apex to Access Salesforce Data
- Wire an Apex Method to a Property
- Wire an Apex Method to a Function
- Apex Wired Method with Params
- Code Snippets with Explanation
Let’s get Started…
Data resides in objects like contact, account, opportunity and now we want to retrieve data into our Lightning Web Component for that we have different set of approaches to do that:
For below three approaches we don’t need to write apex to do get data:
- Use Lightning Data Service to access Salesforce Data
- Use Base Lightning Component to work with Salesforce records
- Use Wire Service to get Salesforce Data
Other approaches are used to retrieve for complex set of data:
- Use Apex Method in Lightning Web Component
- Use API from Apex
- Use of composition to make long running callouts
How to Use Apex to Access Salesforce Data:
Step 1: call apex Method from apex class into JavaScript
- Lightning web components can import methods from Apex classes.
Note: Before you use an Apex method, make sure that there isn’t an easier way to get the data
Syntax
Use default import syntax to import an Apex method
import apexMethodName from '@salesforce/apex/Namespace.Classname.apexMethodReference';
The static import statement is used to import read only live bindings which are exported by another module.
- apexMethodName—A symbol that identifies the Apex method.
- apexMethodReference—The name of the Apex method to import.
- Classname—The name of the Apex class.
- Namespace—If the class is in the same namespace as the component, don’t specify a namespace. If the class is in a managed package, specify the namespace of the managed package.
Interesting Point:
- When an Apex class name changes outside of the JavaScript source file, the class name is automatically updated in the JavaScript source file.
- Method and argument name changes aren’t updated in the JavaScript source file.
Step 2: Call an Apex method as function into Lightning Web Component
- Wire a property
- Wire a function
- Call a method imperatively
Expose Apex Methods to Lightning Web Components
To expose an Apex method to a Lightning web component
- method must be static
- method must be either global or public
- Annotate the method with @AuraEnabled
Enable Client-Side Caching
- Annotating the Apex method with @AuraEnabled(cacheable=true) improves the run time performance.
- To set cacheable=true, a method must only get data, it can’t mutate (change) data.
- Marking a method as cacheable improves component’s performance by quickly showing cached data from client-side storage without waiting for a server trip.
- If the cached data is stale, the framework retrieves the latest data from the server. Caching is especially beneficial for users on high latency, slow, or unreliable connections.
- To use @wire to call an Apex method, you must set cacheable=true
Wire an Apex Method to a Property
If an Apex method is annotated with @AuraEnabled(cacheable=true), we can invoke it from a component via the wire service.
import apexMethodName from '@salesforce/apex/Namespace.Classname.apexMethodReference';
@wire(apexMethodName,{ apexMethodParams })propertyOrFunction;
- apexMethodName—A symbol that identifies the Apex method.
- apexMethodReference—The name of the Apex method to import.
- Classname—The name of the Apex class.
- Namespace—The namespace of the Salesforce organization.
- apexMethodParams—An object with parameters for the apexMethod, if needed. If a parameter value is null, the method is called.
- propertyOrFunction—A private property or function that receives the stream of data from the wire service.
- If a property is decorated with @wire, the results are returned to the property’s data property or error property.
- If a function is decorated with @wire, the results are returned in an object with a data property or an error property.
- NOTE The data property and the error property are hardcoded values in the API. You must use these values.
ContactMaster.apxc
- To get contact data, the component wires an Apex method “getContactList”. The Apex method makes a SOQL query that returns a list of contacts.
- Method must be static, and global or public. The method must be decorated with @AuraEnabled(cacheable=true).
public with sharing class ContactMaster { @AuraEnabled(cacheable=true) public static List<Contact> getContactList() { List<Contact> conList= [SELECT Id, Name, Title, Phone, Email FROM Contact LIMIT 10]; return conList; } }
contactList.js
- The component’s JavaScript code imports the Apex method and invokes it through the wire service.
- The wire service either gets the list of contacts to the contacts.data property, or returns an error to the contacts.error property.
import { LightningElement, wire } from 'lwc'; import getContactList from '@salesforce/apex/ContactMaster.getContactList'; export default class contactList extends LightningElement { @wire(getContactList) contacts; }
contactList.html
The template uses the if:true directive to check whether the contacts.data property is true. If it is, it iterates over it and renders the name of each contact.
<template> <lightning-card title="ApexWireMethodToProperty" icon-name="custom:custom63"> <div class="slds-m-around_medium"> <template if:true={contacts.data}> <template for:each={contacts.data} for:item="contact"> <p key={contact.Id}>{contact.Name}</p> </template> </template> <template if:true={contacts.error}> <c-error-panel errors={contacts.error}></c-error-panel> </template> </div> </lightning-card> </template>
Output
errorPanel.html
For Handling errors
<template> <template if:true={errors}> status: {errors.status}<br /> statusText: {errors.statusText}<br /> <template for:each={errors.body} for:item="error"> statusText: {error.message} </template> </template> </template>
errorPanel.js
import { LightningElement,api } from 'lwc'; export default class ErrorPanel extends LightningElement { @api errors; }
Interesting Point:
The property is assigned a default value after component construction and before any other lifecycle event. Therefore, we can access the property’s value in any function, including functions used by the template or used as part of the component’s lifecycle.
Wire an Apex Method to a Function
This component wires an Apex method call to a function. Because the results are coming to a function, the JavaScript can work on the results.
Also, the template accesses the data a bit differently than if results were provisioned to a property.
ContactMaster.apxc
- This component calls the Apex method as apexWireMethodToProperty.
- The method must be static, and global or public. The method must be decorated with @AuraEnabled(cacheable=true).
public with sharing class ContactMaster { @AuraEnabled(cacheable=true) public static List<Contact> getContactList() { List<Contact> conList= [SELECT Id, Name, Title, Phone, Email FROM Contact LIMIT 10]; return conList; } }
contactDisplay.js
- The component’s JavaScript code imports the Apex method and invokes it via the wire service.
- The wire service gets the results to the wiredContacts() function via an object with either an error or data property.
- If the wire service provisions data, it’s assigned to this.contacts, which is used in the template.
- If it provisions error, it’s assigned to this.error, which is also used in the template. If the value of these properties change, the template rerenders.
import { LightningElement, wire } from 'lwc'; import getContactList from '@salesforce/apex/ContactMaster.getContactList'; export default class contactDisplay extends LightningElement { contacts; error; @wire(getContactList) wiredContacts({ error, data }) { if (data) { console.log('data: ', data); this.contacts = data; console.log('this.contacts: ', this.contacts); this.error = undefined; console.log('this.error: ', this.error); } else if (error) { console.log('error ', error); this.error = error; console.log('this.error: ', this.error); this.contacts = undefined; console.log('this.contacts : ', this.contacts); } } }
contactDisplay.html
- The template uses the if:true directive to check for the JavaScript contacts property. If it exists, it iterates over it and renders the name of each contact.
- If the error property exists, the component renders <c-error-panel>.
<template> <lightning-card title="Apex Wire Method To Function" icon-name="custom:custom63"> <div class="slds-m-around_medium"> <template if:true={contacts}> <template for:each={contacts} for:item="contact"> <p key={contact.Id}>{contact.Name}</p> </template> </template> <template if:true={error}> <c-error-panel errors={error}></c-error-panel> </template> </div> </lightning-card> </template>
Output
Apex Wired Method with Params
ContactMaster.apxc
The Apex method “findContacts” takes a string parameter “searchKey” and returns a list of contacts
public with sharing class ContactMaster { @AuraEnabled(cacheable=true) public static list<Contact> findContacts(String searchKey){ String key = '%' + searchKey + '%'; List<Contact> conlist = [SELECT Id,Name from Contact WHERE Name LIKE :key LIMIT 10 ]; return conlist; } }
contactDisplay.html
The template uses “searchKey” as value in input field
<template> <lightning-card title="Apex Wire Method With Params" > <div class="slds-var-m-around_medium"> <lightning-input type="search" onchange={handleKeyChange} class="slds-var-m-bottom_small" label="Search" value={searchKey} ></lightning-input> <template if:true={contacts.data}> <template for:each={contacts.data} for:item="contact"> <p key={contact.Id}>{contact.Name}</p> </template> </template> <template if:true={contacts.error}> <c-error-panel errors={contacts.error}></c-error-panel> </template> </div> </lightning-card> </template>
contactDisplay.js
- JavaScript shows the value of the searchkey parameter with $ to indicate that it’s dynamic and reactive.
- It references a property of the component instance. If its value changes, the template rerenders.
import { LightningElement, wire } from 'lwc'; import findContacts from '@salesforce/apex/ContactMaster.findContacts'; export default class ContactDisplaywithParameters extends LightningElement { searchKey = ''; @wire(findContacts, { searchKey: '$searchKey' }) contacts; handleKeyChange(event) { const searchValue = event.target.value; this.sexarchKey = searchValue; } }
Output
Together we can learn faster !
Join LWC study group on Telegram
Subscribe to Youtube channel and blog to get latest updates
Reference