Agenda
- Import Apex Methods
- Expose Apex Methods to Lightning Web Component
- Wire Apex Methods
- Imperative Apex Methods
Import Apex Methods
In Lightning Web Components you can use import syntax in JavaScript to import an Apex method via the @salesforce/apex scoped package. We have used below syntax in the Aura Coexistence example.
1 | import getAccList from '@salesforce/apex/AccountController.getAccList'; |
- import getAccList - A name for JS that identifies the Apex method.
- AccountController.getAccList - Apex Class and Name of the method to import.
Expose Apex Methods
To expose an Apex method to a Lightning Web Component, the method must be static and either global or public. Also the method must be annotated with @AuraEnabled.
1 2 3 4 5 6 | public with sharing class AccountController{ @AuraEnabled(cacheable=true) public static List<Account> getAccList(){ return [SELECT Id, Name, Phone FROM ACCOUNT ORDER BY CreatedDate desc Limit 10]; } } |
Wire Apex methods in LWC
To read Salesforce data, Lightning web components use a reactive wire service. Use @wire in a component’s JavaScript class to specify an Apex method. You can @wire a property or a function to receive the data. To operate on the returned data, @wire a function.
Let's understand it by an example, we will bind getAccList method from AccountController to a Lightning Web Component.
You can bind it using wire property & functions which we learned in previous session.
Wire with Property
WireWithProperty html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <template> <lightning-card title="Wired with Property" icon-name="utility:user"> <template if:true={accounts.data}> <div class="slds-var-m-around_medium"> <template for:each={accounts.data} for:item="acc"> <lightning-layout key={acc.Id} class="slds-var-m-vertical_x-small"> <lightning-layout-item flexibility="grow"> {acc.Name} </lightning-layout-item> </lightning-layout> </template> </div> </template> </lightning-card> </template> |
WireWithProperty JS
1 2 3 4 5 6 | import { LightningElement, wire } from 'lwc'; import getAccountList from '@salesforce/apex/AccountController.getAccList'; export default class BindWirewithProperty extends LightningElement { @wire(getAccountList) accounts; } |
Wire with Function
WireWithFunction html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <template> <lightning-card title="Wired with Function" icon-name="utility:user"> <template if:true={accounts}> <div class="slds-var-m-around_medium"> <template for:each={accounts} for:item="acc"> <lightning-layout key={acc.Id} class="slds-var-m-vertical_x-small"> <lightning-layout-item flexibility="grow"> {acc.Name} </lightning-layout-item> </lightning-layout> </template> </div> <div class="slds-var-m-around_medium"> <br/> {error} </div> </template> </lightning-card> </template> |
WireWithFunction JS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import { LightningElement, wire } from 'lwc'; import getAccountList from '@salesforce/apex/AccountController.getAccList'; export default class BindWirewithFunction extends LightningElement { accounts; error; @wire(getAccountList) wiredAccounts({error, data}){ if(data){ this.accounts = data; this.error = undefined; } else if(error){ this.error = error; this.accounts = undefined; } } } |
Imperative Apex
Whenever you have requirement to control a method invocation, let’s say maybe on a button’s click, you can call the method imperatively.
In the following scenarios, you must call an Apex method imperatively as opposed to using @wire.
- To call a method that isn’t annotated with cacheable=true, which includes any method that inserts, updates, or deletes data.
- To control when the invocation occurs.
- To work with objects that aren’t supported by User Interface API, like Task and Event.
- To call a method from an ES6 module that doesn’t extend LightningElement
Let’s understand it by calling the same Apex method which we used for wire callout as imperatively.
JS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import { LightningElement } from 'lwc'; import getAccountList from '@salesforce/apex/AccountController.getAccList'; export default class BindImperativeMethod extends LightningElement { accounts; error; buttonClick(){ getAccountList() .then((result) =>{ this.accounts = result; this.error = undefined; }) .catch((error)=>{ this.error = error; this.accounts = undefined; }); } } |
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <template> <lightning-card title="Wired using Imperative Method" icon-name="utility:user"> <div class="slds-var-m-around_medium"> <lightning-button label="Get Accounts" onclick={buttonClick}> </lightning-button> </div> <template if:true={accounts}> <div class="slds-var-m-around_medium"> <template for:each={accounts} for:item="acc"> <lightning-layout key={acc.Id} class="slds-var-m-vertical_x-small"> <lightning-layout-item flexibility="grow"> {acc.Name} </lightning-layout-item> </lightning-layout> </template> </div> <div class="slds-var-m-around_medium"> <br/> {error} </div> </template> </lightning-card> </template> |
Like our other examples, the template uses if:true to render the list of accounts or an error panel. It also uses for:each to iterate over the accounts.
We can also pass parameters while calling Apex methods, let’s understand it using previous example but we will be passing a string also this time.
AccountController.apxc
1 2 3 4 5 6 7 | public with sharing class AccountController{ @AuraEnabled(cacheable=true) public static List<Account> findAccList(String keyword){ String key='%'+keyword+'%'; return [SELECT Id, Name,Phone FROM ACCOUNT WHERE Name LIKE:key ORDER BY CreatedDate desc Limit 10]; } } |
LWC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <template> <lightning-card title="Bind Imperative Method with Param" icon-name="utility:user"> <div class="slds-var-m-around_medium"> <lightning-input onchange={handleonchange} label="Search Account" value={searchKey}> </lightning-input> </div> <div class="slds-var-m-around_medium"> <lightning-button label="Get Accounts" onclick={buttonClick}> </lightning-button> </div> <template if:true={accounts}> <div class="slds-var-m-around_medium"> <template for:each={accounts} for:item="acc"> <lightning-layout key={acc.Id} class="slds-var-m-vertical_x-small"> <lightning-layout-item flexibility="grow"> {acc.Name} </lightning-layout-item> </lightning-layout> </template> </div> <div class="slds-var-m-around_medium"> <br/> {error} </div> </template> </lightning-card> </template> |
JS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | import { LightningElement } from 'lwc'; import findAccountList from '@salesforce/apex/AccountController.findAccList'; export default class BindImperativewithParam extends LightningElement { searchKey=''; accounts; error; handleonchange(event){ this.searchKey = event.target.value; } buttonClick(){ findAccountList({keyword: this.searchKey}) .then((result) =>{ this.accounts = result; this.error = undefined; }) .catch((error)=>{ this.error = error; this.accounts = undefined; }); } } |
0 Comments