Exploitation des données avec Apex
Objectifs de formation
Une fois cette unité terminée, vous pourrez :
- Savoir quand utiliser Apex pour exploiter des données Salesforce
- Appeler Apex de deux manières différentes
- Exploiter des listes d’enregistrements avec Apex et lightning-datatable
Apex dans les composants Web Lightning
Nous avons étudié les avantages de Lightning Data Service et les façons de l’utiliser. Il arrive cependant que ni les composants lightning-record-*-form
, ni les adaptateurs Wire et les fonctions de LDS ne conviennent à un cas d’utilisation spécifique. Par exemple, lorsque vous souhaitez personnaliser une transaction de données à enregistrement unique ou effectuer des opérations sur des enregistrements multiples dans une seule transaction, Apex est la solution idéale.
Utilisation des méthodes Apex avec les composants Web Lightning
Une méthode Apex utilisée dans un composant Web Lightning doit être de type static
, public
ou global
et annotée avec @AuraEnabled
juste avant la définition de la méthode. L’annotation @AuraEnabled
rend la méthode Apex accessible aux composants Lightning (aussi bien les composants Web Lightning que les composants Aura).
Permettre à l’infrastructure de mettre en cache les données élimine les appels répétés au serveur, ce qui accélère l’exécution des futures opérations de lecture. Nous indiquons qu’une méthode peut être mise en cache en définissant cacheable=true
dans l’annotation @AuraEnabled
. Lorsqu’une méthode @AuraEnabled
peut être mise en cache, les opérations DML (Data Manipulation Language, ou langage de manipulation de données) ne sont pas autorisées. À la ligne 2 de cet exemple, nous rendons possible la mise en cache de la méthode getContactsBornAfter
.
ContactController.cls
public with sharing class ContactController { @AuraEnabled(cacheable=true) public static List<Contact> getContactsBornAfter(Date birthDate) { return [ SELECT Name, Title, Email, Phone FROM Contact WHERE Birthdate > :birthDate WITH SECURITY_ENFORCED ]; } }
Lorsqu’une méthode peut être mise en cache, il est possible que les versions nouvellement ajoutées ou modifiées des enregistrements ne soient pas renvoyées tant que le cache n’est pas actualisé. Vous apprendrez comment actualiser manuellement le cache dans la section suivante.
Appel de méthodes Apex à partir de composants Web Lightning (LWC)
Il existe deux façons d’interagir avec les méthodes Apex dans les composants Web Lightning : en liant la méthode ou en l’appelant de manière impérative. Examinons ces deux approches.
Appel d’Apex à l’aide de @wire
Pour lier une méthode Apex, celle-ci doit pouvoir être mise en cache. Pour lier une méthode Apex pouvant être mise en cache, utilisez le décorateur @wire
(de la même manière que vous utiliseriez un adaptateur Wire de LDS). Le fait d’appeler Apex de cette manière délègue le contrôle au moteur des composants Lightning Web et crée un service réactif. Chaque fois que la valeur d’un paramètre transmis à la méthode Apex est modifiée, celle-ci s’exécute en provisionnant la nouvelle valeur à la propriété ou à la fonction décorée. Étant donné que les méthodes liées doivent pouvoir être mises en cache, les données peuvent provenir du cache LDS ou du serveur. Pour actualiser les données mises en cache par une méthode Apex, appelez la fonction refreshApex.
Remarque : Lightning Data Service est isolé des données mises en cache par les méthodes Apex. Lorsqu’une fonction LDS met à jour un enregistrement, cette mise à jour n’a aucun effet sur les données mises en cache par une méthode Apex.
Voici un exemple d’utilisation de @wire
pour appeler Apex. Ce code permet d’obtenir les contacts qui sont nés après la date spécifiée.
wireApexProperty.js
import { LightningElement, api, wire } from 'lwc'; import getContactsBornAfter from '@salesforce/apex/ContactController.getContactsBornAfter'; export default class WireApexProperty extends LightningElement { @api minBirthDate; @wire(getContactsBornAfter, { birthDate: '$minBirthDate' }) contacts; }
Points marquants du code :
- Ligne 2 : nous importons la fonction
getContactsBornAfter
à partir de la classe ApexContactController
, qui est reliée à la méthode Apex correspondante. - Ligne 4 : nous définissons une propriété
@api minBirthDate
. Lorsque vous utilisez ce composant dans votre code ou exposez un attribut FlexiPage, vous pouvez transmettre une date à la propriété@api minBirthDate
. - Ligne 5 : le décorateur
@wire
reçoit deux paramètres : la méthode Apex que nous souhaitons appeler (getContactsBornAfter
) et le paramètre dont l’adaptateur a besoin (birthDate
). Nous transmettons$minBirthDate
en tant que variable réactive (commençant par$
). - Ligne 6 : le résultat est stocké dans la propriété
contacts
. - Lignes 5 à 6 : la méthode Apex transmet dans un premier temps les données à la propriété
contacts
et stocke ces données dans le cache LDS.$minBirthDate
étant réactif, la méthode Apex s’exécute et provisionne de nouvelles données à chaque fois que sa valeur change, à partir du cache ou du serveur.
Appel d’Apex de manière impérative
L’appel impératif d’Apex constitue une alternative à l’appel d’Apex avec @wire
. Appelez Apex de manière impérative lorsque vous devez contrôler l’invocation des opérations de lecture et lorsque vous modifiez des enregistrements. Pour appeler Apex de manière impérative, invoquez la fonction importée depuis le fichier JavaScript du composant. La fonction renvoie une promesse JavaScript (comme c’est le cas lorsque vous appelez une fonction LDS de manière impérative).
Vous pouvez appeler les méthodes Apex pouvant être mises en cache ou non de manière impérative. Cependant, vous ne pouvez pas actualiser de manière impérative une méthode Apex pouvant être mise en cache. À la place, appelez la méthode en utilisant @wire
et actualisez-la avec refreshApex
.
Dans l’exemple callApexImperative.js, lorsqu’un utilisateur clique sur un bouton lightning-button
dans le fichier .html (non représenté ici), handleButtonClick
appelle de manière impérative la méthode Apex getContactsBornAfter
.
callApexImperative.js
import { LightningElement, api, wire } from 'lwc'; import getContactsBornAfter from '@salesforce/apex/ContactController.getContactsBornAfter'; export default class CallApexImperative extends LightningElement { @api minBirthDate; handleButtonClick() { getContactsBornAfter({ //imperative Apex call birthDate: this.minBirthDate }) .then(contacts => { //code to execute if related contacts are returned successfully }) .catch(error => { //code to execute if related contacts are not returned successfully }); } }
Points marquants du code :
- Ligne 2 : nous importons la fonction
getContactsBornAfter
à partir de la classeContactController
. - Ligne 4 : nous définissons une propriété publique
minBirthDate
, à laquelle vous pouvez transmettre une date lorsque vous utilisez ce composant dans votre code ou lorsque vous exposez un attribut FlexiPage. - Lignes 6 à 7 : lorsque la méthode
handleButtonClick
est invoquée par l’infrastructure, nous invoquons de manière impérative la méthode ApexgetContactsBornAfter
en transmettant le paramètrebirthDate
dont la méthode a besoin pour obtenir les contacts nés après la date spécifiée. - Lignes 9 à 14 : l’appel Apex impératif de la ligne 6 a renvoyé une promesse. Lorsque l’appel de la méthode Apex aboutit, la promesse est exécutée et la méthode
then
s’exécute. Dans le cas contraire, la promesse est rejetée et la méthodecatch
s’exécute.
La meilleure façon d’exploiter des listes d’enregistrements dans les composants Web Lightning consiste à utiliser le composant de base lightning-datatable
. Utilisez lightning-datatable
pour créer des tableaux de données comportant des fonctionnalités telles que le défilement infini, la modification en ligne, les actions au niveau de l’en-tête et de la ligne, le redimensionnement, etc. Ce composant d’interface utilisateur doit être alimenté en données. La manière la plus courante de générer ces données consiste à appeler Apex de l’une des manières expliquées précédemment dans ce module.
Déploiement d’un composant Web Lightning de répertoriage d’enregistrements dans un tableau
Prenons un exemple qui affiche une liste de comptes existants dans un composant lightning-datatable
. Nous utiliserons Apex et @wire
pour récupérer les enregistrements.
- Créez une classe Apex nommée
AccountController
:
- dans le volet Explorateur, cliquez avec le bouton droit de la souris sur le dossier classes et sélectionnez SFDX : Créer une classe Apex.
- Pour le nom de la classe, saisissez
AccountController
et appuyez sur Entrée. - Appuyez de nouveau sur Entrée pour accepter le répertoire par défaut.
- Remplacez le contenu de votre classe AccountController par le code suivant :Points marquants du code :
public with sharing class AccountController { @AuraEnabled(cacheable=true) public static List<Account> getAccounts() { return [ SELECT Name, AnnualRevenue, Industry FROM Account WITH SECURITY_ENFORCED ORDER BY Name ]; } }
- Ligne 2 : nous annotons la méthode avec
@AuraEnabled(cacheable=true)
afin que les résultats soient mis en cache. - Ligne 3 : nous définissons la méthode
getAccounts
dans Apex, afin d’effectuer une opération de lecture et de récupérer les comptes existants.
- Créez un composant Web Lightning nommé
accountList
. - Remplacez le contenu de votre fichier accountList.js par le code suivant :Points marquants du code :
import { LightningElement, wire } from 'lwc'; import NAME_FIELD from '@salesforce/schema/Account.Name'; import REVENUE_FIELD from '@salesforce/schema/Account.AnnualRevenue'; import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry'; import getAccounts from '@salesforce/apex/AccountController.getAccounts'; const COLUMNS = [ { label: 'Account Name', fieldName: NAME_FIELD.fieldApiName, type: 'text' }, { label: 'Annual Revenue', fieldName: REVENUE_FIELD.fieldApiName, type: 'currency' }, { label: 'Industry', fieldName: INDUSTRY_FIELD.fieldApiName, type: 'text' } ]; export default class AccountList extends LightningElement { columns = COLUMNS; @wire(getAccounts) accounts; }
- Lignes 2 à 4 : nous importons des références de champs, comme dans les exemples précédents.
- Ligne 5 : nous importons la fonction
getAccounts
de la classe AccountController. - Ligne 13 : nous utilisons
@wire
avec la fonctiongetAccounts
pour récupérer les données. - Ligne 14 : nous stockons le résultat dans la propriété
accounts
. Si l’opération aboutit, les enregistrements sont accessibles dansaccounts.data
. En cas d’échec, l’erreur apparaît dansaccounts.error
.
- Remplacez le contenu de votre fichier accountList.html par le code suivant :Points marquants du code :
<template> <lightning-card> <template if:true={accounts.data}> <lightning-datatable key-field="Id" data={accounts.data} columns={columns} > </lightning-datatable> </template> </lightning-card> </template>
- Lignes 4 à 9 : nous définissons le composant de base
lightning-datatable
de manière à ce qu’il utilise les informationsaccounts.data
etcolumns
qui se trouvent dans le fichier JavaScript.
- Enregistrez votre classe AccountController.
- Remplacez le contenu de votre fichier accountList.js-meta.xml par le code suivant afin que le composant soit accessible sur les pages de l’application :
<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>48.0</apiVersion> <isExposed>true</isExposed> <targets> <target>lightning__AppPage</target> </targets> </LightningComponentBundle>
- Enregistrez les trois fichiers de composant.
- Déployez le dossier force-app/main/default dans votre Trailhead Playground.
- Dans votre Trailhead Playground, accédez au générateur d’applications Lightning et ouvrez la page Working with Data (Utilisation des données).
- Faites glisser le composant accountList vers la zone principale de la page.
- Enregistrez la page.
- Revenez à la page Working with Data (Utilisation des données) pour visualiser votre nouveau composant.
Vous connaissez désormais plusieurs façons d’interagir avec les données Salesforce dans vos composants Web Lightning. Vous allez maintenant apprendre à gérer les éventuelles erreurs de serveur.
Ressources