#7: Work with Apex in LWC | Learn Lightning Web Component Development | LWC Stack Salesforce


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;
        });

    }
}


Checkout the Crash Course Below


 If you have any question please leave a comment below.

If you would like to add something to this post please leave a comment below.
Share this blog with your friends if you find it helpful somehow !

Thanks

Happy Coding :)

Post a Comment

0 Comments