Suivez votre progression
Accueil Trailhead
Accueil Trailhead

Traitement des modifications d’enregistrements et des erreurs

Objectifs de formation

Une fois cette unité terminée, vous pourrez :

  • Expliquer comment Lightning Data Service pour les composants Aura utilise les notifications.
  • Utiliser recordUpdated pour traiter les erreurs et enregistrer les changements.

Modification d’un enregistrement

Dans l’unité précédente, nous avons vu comment Lightning Data Service traite CRUD. Voyons maintenant comment effectuer des actions lorsque l’enregistrement est modifié, pour que vos composants puissent répondre au chargement, à la modification, à la mise à jour ou à la suppression d’un enregistrement.

Pour effectuer une action lorsqu’un enregistrement est modifié, traitez l’événement recordUpdated.

<force:recordData aura:id="forceRecordDataCmp"
    recordId="{!v.recordId}" 
    layoutType="{!v.layout}"
    targetRecord="{!v.record}"
    targetFields="{!v.simpleRecord}"
    targetError="{!v.error}"
    recordUpdated="{!c.recordUpdated}" />

Implémentez un gestionnaire d’action qui traitera la modification. Les champs modifiés sont indiqués par l’objet changedFields, qui contient les anciennes valeurs des champs et les nouvelles valeurs correspondantes.

({
    recordUpdated: function(component, event, helper) {
        var eventParams = event.getParams();
        if(eventParams.changeType === "CHANGED") {
            // get the fields that are changed for this record
            var changedFields = eventParams.changedFields;
            console.log('Fields that are changed: ' + JSON.stringify(changedFields));
            // record is changed so refresh the component (or other component logic)
            var resultsToast = $A.get("e.force:showToast");
            resultsToast.setParams({
                "title": "Saved",
                "message": "The record was updated."
            });
            resultsToast.fire();
        } else if(eventParams.changeType === "LOADED") {
            console.log("Record is loaded successfully.");
        } else if(eventParams.changeType === "REMOVED") {
            var resultsToast = $A.get("e.force:showToast");
            resultsToast.setParams({
                "title": "Deleted",
                "message": "The record was deleted."
            });
            resultsToast.fire();
        } else if(eventParams.changeType === "ERROR") {
            console.log('Error: ' + component.get("v.error"));
        }
    }
})

Lorsque LDS détecte une modification d’un enregistrement, il notifie les composants qui utilisent l’enregistrement de la modification. Si vous ne traitez pas la modification, l’enregistrement est quand même mis à jour. Toutes les références aux propriétés targetRecord ou targetFields apparaissent donc automatiquement dans vos composants. Pour chaque composant force:recordData qui fait référence à l’enregistrement modifié, LDS fait deux choses.

  • LDS notifie de la modification toutes les autres instances de force:recordData en déclenchant l’événement recordUpdated avec les valeurs changeType et changedFields correspondantes.
  • Il définit les attributs targetRecord et targetFields de chaque force:recordData sur la nouvelle valeur de l’enregistrement. Si un élément de l’interface utilisateur fait référence à targetRecord ou targetFields, un rafraîchissement est déclenché automatiquement de manière à ce que l’interface utilisateur affiche les dernières données.
Remarque

Remarque

Si force:recordData est en mode EDIT, targetRecord et targetFields ne sont pas mis à jour automatiquement lorsque l’enregistrement est modifié. L’objectif est de ne pas envoyer trop tôt des modifications encore en cours et d’éviter que des modifications non enregistrées n’apparaissent dans d’autres composants. Ne vous inquiétez pas, les enregistrements peuvent être rafraîchis manuellement en traitant l’événement recordUpdated et en appelant la méthode reloadRecord.

Lorsque LDS détecte une modification provenant du serveur, il utilise le même mécanisme de notification des changements. LDS détecte une modification sur le serveur lorsqu’il reçoit une nouvelle demande d’enregistrement. LDS ne notifie que les composants enregistrés et marqués comme isValid. Lorsque vous traitez l’événement recordUpdated, vérifiez le changeType pour savoir quel type de changement vous allez traiter.

Gestion des erreurs

Si une erreur a lieu au chargement, un message d’erreur localisé est placé dans l’attribut targetError. Une erreur a lieu quand les attributs de force:recordData ne sont pas valides, ou si le serveur ne peut être contacté et que l’enregistrement ne se trouve pas dans le cache local. Il vous appartient alors de choisir comment afficher l’erreur.

Si l’enregistrement devient inaccessible sur le serveur, l’événement recordUpdated se déclenche avec changeType = REMOVED, et aucune erreur n’est attribuée à targetError, car le fait qu’un enregistrement soit inaccessible peut parfois être le résultat attendu. Les enregistrements peuvent également devenir inaccessibles en raison de partages et de paramètres de visibilité sur des enregistrements ou des entités, ou parce que l’enregistrement a été supprimé.

Petit récapitulatif

Félicitations ! Vous avez maintenant toutes les cartes en main pour vous lancer avec Lightning Data Service. Il est relativement simple, mais très puissant ! Avant de vous remettre un beau badge tout neuf, mettons un peu toute cette théorie en pratique. Nous allons créer une page qui contient deux composants qui utilisent les mêmes données d’enregistrement et répondent correctement à une modification de l’enregistrement.

Le composant affiche les détails d’un contact. Notez qu’il utilise fields à la place de layoutType, et targetFields plutôt que targetRecord. Souvenez-vous qu’il est possible d’inclure fields ou layoutType (ou les deux !), et que vous pouvez utiliser targetFields ou targetRecord (ou les deux !) pour récupérer les données de l’enregistrement. Avec fields, vous devez spécifier quels champs vous souhaitez interroger, tandis qu’avec layoutType, il suffit de préciser le type de présentation d’enregistrement que vous souhaitez utiliser, FULL ou COMPACT. Si vous utilisez targetFields pour récupérer des données, ce qui recommandé, utilisez le format v.targetFields.Name dans votre interface utilisateur. Si vous utilisez targetRecord, utilisez v.targetRecord.fields.Name.value.

ldsShowContact.cmp
<aura:component implements="force:hasRecordId,flexipage:availableForRecordHome">

    <aura:attribute name="contactRecord" type="Object"/>
    <aura:attribute name="recordLoadError" type="String"/>
    
    <force:recordData aura:id="recordLoader"
        recordId="{!v.recordId}"
        fields="Name,Description,Phone"
        targetFields="{!v.contactRecord}"
        targetError="{!v.recordLoadError}"
    />

    <!-- Display a lightning card with details about the contact -->
    <lightning:card iconName="standard:contact" title="{!v.contactRecord.Name}" >
        <div class="slds-p-horizontal--small">
            <p class="slds-text-heading--small">
                <lightning:formattedPhone title="Phone"  value="{!v.contactRecord.Phone}" /></p>
            <p class="slds-text-heading--small">
                <lightning:formattedText title="Description" value="{!v.contactRecord.Description}" /></p>
        </div>
    </lightning:card>

</aura:component>

Notre composant suivant charge le même contact, mais en mode EDIT, avec un formulaire qui permet à l’utilisateur de modifier le contact lui-même. Il s’occupe également de l’événement recordUpdated pour que nous puissions effectuer certaines actions en fonction du résultat de la modification.

ldsEditContact.cmp
<aura:component implements="force:hasRecordId,flexipage:availableForRecordHome">

    <aura:attribute name="contactRecord" type="Object"/>
    <aura:attribute name="recordSaveError" type="String" default=""/>

    <!-- Load record in EDIT mode -->
    <force:recordData aura:id="recordLoader"
        recordId="{!v.recordId}"
        fields="Name,Description,Phone"
        targetFields="{!v.contactRecord}"
        targetError="{!v.recordSaveError}"
        mode="EDIT" 
        recordUpdated="{!c.handleRecordUpdated}" />

    <!-- Contact edit form -->
    <lightning:card iconName="action:edit" title="Edit Contact">
        <div class="slds-p-horizontal--small">
            <lightning:input label="Contact Name" value="{!v.contactRecord.Name}"/>
            <lightning:input label="Contact Description" value="{!v.contactRecord.Description}"/>
            <lightning:input label="Contact Phone" value="{!v.contactRecord.Phone}"/>
            <br/>
            <lightning:button label="Save Contact" variant="brand" onclick="{!c.saveContact}" />
        </div>
    </lightning:card>
    
    <!-- Display error message -->
    <aura:if isTrue="{!not(empty(v.recordSaveError))}">
        <div class="recordSaveError">
            {!v.recordSaveError}</div>
    </aura:if>

</aura:component>

Enfin nous avons notre contrôleur qui signale une modification réussie par un message de félicitation ou affiche un message d’erreur, en fonction du résultat de la modification.

ldsEditContactController.js
({
    saveContact : function(cmp, event, helper) {
        var recordLoader = cmp.find("recordLoader");
        recordLoader.saveRecord($A.getCallback(function(saveResult) {
            if (saveResult.state === "ERROR") {
                var errMsg = "";
                // saveResult.error is an array of errors, 
                // so collect all errors into one message
                for (var i = 0; i < saveResult.error.length; i++) {
                    errMsg += saveResult.error[i].message + "\n";
                }
                cmp.set("v.recordSaveError", errMsg);
            } else {
                cmp.set("v.recordSaveError", "");
            }
        }));
    },

    // Control the component behavior here when record is changed (via any component)
    handleRecordUpdated: function(component, event, helper) {
        var eventParams = event.getParams();
        if(eventParams.changeType === "CHANGED") {
            // get the fields that are changed for this record
            var changedFields = eventParams.changedFields;
            console.log('Fields that are changed: ' + JSON.stringify(changedFields));
            // record is changed so refresh the component (or other component logic)
            var resultsToast = $A.get("e.force:showToast");
            resultsToast.setParams({
                "title": "Saved",
                "message": "The record was updated."
            });
            resultsToast.fire();
        } else if(eventParams.changeType === "LOADED") {
            // record is loaded in the cache
        } else if(eventParams.changeType === "REMOVED") {
            // record is deleted and removed from the cache
        } else if(eventParams.changeType === "ERROR") {
            console.log('Error: ' + component.get("v.error"));
        }
    }
})

Et voilà, vous êtes passé maître dans l’utilisation de Lightning Data Service. Maintenant, il ne vous reste plus qu’à utiliser vos nouveaux pouvoirs pour améliorer les performances et la cohérence de vos composants Lightning pour tous les Trailblazers.