Chapter 30: Access Salesforce Data using Wire Service in Lightning Web Component

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

Understand Data Service

Did you enjoy this article?
Signup today and receive free updates straight in your inbox.
I agree to have my personal information transfered to MailChimp ( more information )
50% LikesVS
50% Dislikes