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 getRelatedContacts.

AccountController.cls

public with sharing class AccountController {
    @AuraEnabled(cacheable=true)
    public static List<Contact> getRelatedContacts(Id accountId) {
        return [
            SELECT Name, Title, Email, Phone
            FROM Contact
            WHERE AccountId = :accountId
            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 attribue 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 associés d’un compte.

wireApexProperty.js

import { LightningElement, api, wire } from 'lwc';
import getRelatedContacts from '@salesforce/apex/AccountController.getRelatedContacts';
export default class WireApexProperty extends LightningElement {
    @api recordId;
    @wire(getRelatedContacts, { accountId: '$recordId' })
    contacts;
}

Points marquants du code :

  • Ligne 2 : nous importons la fonction getRelatedContacts à partir de la classe Apex AccountController, qui est reliée à la méthode Apex correspondante.
  • Ligne 4 : nous définissons une propriété @api recordId, de sorte que la FlexiPage transmette l’ID de l’enregistrement actuel au composant.
  • Ligne 5 : le décorateur @wire reçoit deux paramètres : la méthode Apex que nous souhaitons appeler (getRelatedContacts) et le paramètre dont l’adaptateur a besoin (accountId). Nous transmettons $recordId 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 provisionne dans un premier temps les données à la propriété contacts et stocke ces données dans le cache LDS. $recordId étant réactif, la méthode Apex 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, vous devez l’appeler une fois à partir du fichier JavaScript d’un composant au lieu de déléguer le contrôle au moteur des composants Web Lightning. En retour, vous obtenez 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. Pour actualiser le cache d’une méthode pouvant être mise en cache, appelez à nouveau la méthode.

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 getRelatedContacts.

callApexImperative.js

import { LightningElement, api, wire } from 'lwc';
import getRelatedContacts from '@salesforce/apex/AccountController.getRelatedContacts';
export default class CallApexImperative extends LightningElement {
    @api recordId;
    handleButtonClick() {
        getRelatedContacts({ //imperative Apex call
            accountId: '$recordId'
        })
            .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 getRelatedContacts à partir de la classe AccountController.
  • Ligne 4 : nous définissons une propriété recordId publique, de sorte que la FlexiPage transmette l’ID du compte pour lequel ce composant affiche les contacts associés.
  • Lignes 6 à 7 : lorsque la méthode handleButtonClick est appelée par l’infrastructure, nous appelons de manière impérative la méthode Apex getRelatedContacts en transmettant le paramètre accountId dont la méthode a besoin pour obtenir les contacts associés du compte correspondant.
  • 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éthode catch 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.

  1. Créez une classe Apex nommée AccountController :
    1. 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.
    2. Pour le nom de la classe, saisissez AccountController et appuyez sur Entrée.
    3. Appuyez de nouveau sur Entrée pour accepter le répertoire par défaut.
  2. Remplacez le contenu de votre classe AccountController par le code suivant :
    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
            ];
        }
    }
    Points marquants du code :
    • 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.
  3. Créez un composant Web Lightning nommé accountList.
  4. Remplacez le contenu de votre fichier accountList.js par le code suivant :
    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;
    }

    Points marquants du code :
    • 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 fonction getAccounts 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 dans accounts.data. En cas d’échec, l’erreur apparaît dans accounts.error.
  5. Remplacez le contenu de votre fichier accountList.html par le code suivant :
    <template>
        <lightning-card>
            <template if:true={accounts.data}>
                <lightning-datatable
                    key-field="Id"
                    data={accounts.data}
                    columns={columns}
                >
               </lightning-datatable>
            </template>
        </lightning-card>
    </template>
    Points marquants du code :
    • Lignes 4 à 9 : nous définissons le composant de base lightning-datatable pour qu’il utilise les informations accounts.data et columns qui se trouvent dans le fichier JavaScript.
  6. Enregistrez votre classe AccountController.
  7. 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>
  8. Enregistrez les trois fichiers de composant.
  9. Déployez le dossier force-app/main/default dans votre Trailhead Playground.
  10. Dans votre Trailhead Playground, accédez au générateur d’applications Lightning et ouvrez la page Working with Data.
  11. Faites glisser le composant accountList vers la zone principale de la page.
  12. Enregistrez la page.
  13. Revenez à la page Working with Data pour visualiser votre nouveau composant.
Remarque

Remarque

Voici quelques éléments à prendre en compte lors de l’utilisation du composant lightning-datatable :

  • Certains types de données ne sont actuellement pas pris en charge dans le composant lightning-datatable. Vous pouvez cependant utiliser des types personnalisés. Pour en savoir plus, accédez à la section Création de types de données personnalisés dans la documentation.
  • Le composant lightning-datatable ne fonctionne actuellement pas sur mobile. Si vos données doivent être accessibles sur mobile, créez plutôt un tableau personnalisé.

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