Suivez votre progression
Accueil Trailhead
Accueil Trailhead

Élaboration d'une interface utilisateur pour afficher un enregistrement

Objectifs de formation

Une fois cette unité terminée, vous pourrez :
  • Faire une requête à l'API de l’interface utilisateur pour obtenir les données et les métadonnées d'un enregistrement.
  • Comprendre pourquoi et comment demander des facteurs de forme, des types de dispositions et des modes d'accès.
  • Comprendre pourquoi et comment demander des enregistrements enfants.

Extraction d'un enregistrement

Un autre atout de l'API de l’interface utilisateur est qu'elle rassemble ce dont vous avez besoin pour concevoir l'IU. Savez-vous combien de requêtes HTTP sont nécessaires pour obtenir les métadonnées d'objets, les métadonnées de présentation et les données de champs nécessaires pour afficher l'enregistrement Universal Container ? Une.

/ui-api/record-ui/{recordIds}

Voyons à quoi ressemble la requête dans le code de Record Viewer. Accédez au fichier /client-src/sagas/recordFetcher.js. Vous pouvez examiner sur GitHub ou sur votre machine locale.

Cette ligne construit l'URL cible de l'API d'IU.
let recordViewUrl = action.creds.instanceUrl + '/services/data/v48.0/ui-api/record-ui/' 
  + action.recordId + '?formFactor=' + action.context.formFactor + '&layoutTypes=Full&modes=View,Edit';

La requête envoie un ID d'enregistrement, action.recordId, qui est l'enregistrement que l'utilisateur a choisi dans la liste Éléments récents. (Le point de terminaison prend en charge plusieurs ID d'enregistrement, mais les requêtes de l'application Record Viewer un seul.)

La réponse comprend les informations de présentation, qui vous indiquent où sont placés les champs et quelles sections de l'IU y figurent. Elle vous indique également quelles sections sont réduites, ce que nous appelons l'état utilisateur de présentation.

Pour indiquer ce qu’il convient d’inclure dans les informations de présentation, la demande utilise les paramètres suivants : formFactor, layoutTypes et modes.

form factor change la présentation des champs. Choisissez un facteur de forme qui correspond au type de matériel sur lequel tourne l'application. Large est une présentation pour les clients de bureau. Medium est une présentation pour les tablettes et Small pour les téléphones. Dans les facteurs de forme large et medium, les sections ont une présentation sur deux colonnes. Dans le facteur de forme small, les sections ont une présentation en une colonne.

layout type détermine combien de champs sont renvoyés. Les types de présentations possibles sont Full et Compact. La présentation full par défaut comprend tous les champs de la présentation de page affectée à l'utilisateur actuel. La présentation compact par défaut comprend tous les champs de la présentation compact affectée à l'utilisateur actuel. Vous pouvez modifier les deux types de présentations dans Configuration. Quel que soit le type de présentation, la réponse comprend uniquement les champs auxquels l'utilisateur a accès.

mode correspond à la tâche que l'utilisateur est en train d'exécuter : Create, View ou Edit. Les informations de présentation diffèrent en fonction du mode. Par exemple, en mode de création, la présentation ne comprend pas la section Informations système, qui comporte des champs tels que Créateur ou Dernière modification effectuée par.

L'application Record Viewer interroge les modes d'affichage et de modification, de sorte que si un utilisateur clique sur Modifier, l'application possède déjà les informations nécessaires pour rendre l'IU.

Conseil

Conseil

Pour renvoyer des enregistrements enfant sans avoir à créer de requêtes qui associent deux enregistrements, utilisez le paramètre childRelationships. La réponse est paginée et comprend un niveau de relations enfant. Par exemple, la requête renvoie à un enregistrement Compte et ses enregistrements enfant Opportunité.

/ui-api/record-ui/001R0000003IG0vIAG?childRelationships=Account.Opportunities

Envoi de requêtes et mise à jour de l'état global

L'application RecordViewer envoie des requêtes REST aux points de terminaison de l'API d'IU et met à jour de manière asynchrone son état Redux avec ces informations. Puis, l'arborescence des composants de React... réagit (eh oui) au changement d'état et met à jour l'IU.

Les sagas de Redux gèrent les requêtes REST de l'application. La requête /ui-api/record-ui/{recordIds} est exécutée à l'aide de la saga recordFetcher.js. Ce code construit l'URL REST et émet la requête à l'aide du jeton d'accès Oauth en tant que Bearer. Elle configure également l'en-tête X-Chatter-Entity-Encoding sur false pour s'assurer que des caractères spéciaux dans le JSON ne sont pas du HTML échappé.

Lorsque la réponse revient, et que le JSON a été correctement analysé, la saga termine en envoyant une action RECEIVE_RECORD qui comprend la réponse JSON. Dans le modèle Redux, les actions sont émises pour exprimer une intention de modifier l'état global. En séparant les opérations pour effectuer la requête externe, modifier l'état et mettre à jour le composant, nous maintenons les choses étroitement imbriquées.

Dans Redux, les reducers interceptent les actions et les utilisent pour transformer des aspects de l'état global. Dans ce cas, pour effectuer une mise à jour de la partie « enregistrement » de l'état global, le reducer record.js intercepte l'action RECEIVE_RECORD et traite son JSON.
/* /reducers/record.js */
case 'RECEIVE_RECORD':
      return {
        record: recordLayout.getLayoutModel(action.recordId, action.record),
        mode: 'View'
      }

La charge de travail JSON se trouve dans action.record. Le nouvel état résultant est disponible pour les composants via state.record. Cette partie de l'état provenant du reducer record.js est assemblée dans l'état global dans reducers/index.js.

Analyse de la réponse JSON et affichage de l'enregistrement

Maintenant, examinons l'aide recordLayout.getLayoutModel() qui est utilisée dans le reducer d'état record.js. Elle traite les données de l'enregistrement, les présentations et les informations de l'objet à partir du JSON /ui-api/record-ui/{recordIds} pour en faire une structure de données. Cette structure de données est l'état qui alimente les composants React de l'application.

À la base du fichier /client-src/helpers/recordLayout.js, getLayoutModel() assemble un objet détenant :
  • les informations de la présentation
  • une carte de editValues utilisée pour suivre les modifications apportées aux valeurs du champ dans l'IU
  • le objectInfo unique qui correspond à l'enregistrement en main
  • l'ID de l'enregistrement

La fonction recordLayout.getLayoutModel() traite les informations de la présentation en faisant des boucles dans les présentations. Pour chaque section de chaque présentation de la réponse, nous appelons getLayoutSectionModel(). Cette méthode récupère les informations de l'en-tête de la section à partir de la section JSON. Puis, elle effectue une boucle dans chaque ligne de la section, et dans chaque ligne elle effectue une boucle sur chaque élément de la présentation.

Pour chaque élément de la présentation getLayoutItemModel() assemble un objet qui contient :
  • une liste imbriquée de valeurs (il peut exister plusieurs valeurs dans un élément pour des choses telles que des adresses.)
  • des informations de liaison (des liens vers d'autres enregistrements)
  • des informations de liens personnalisés (des liens vers des URL externes)

Chacune des valeurs contient des informations sur ce qui doit être affiché sous forme de texte, l'étiquette, les métadonnées du champ, la possibilité de modifications et l'URL de la liste de sélection de l'API d'IU correspondante, le cas échéant.

Il existe quelques cas particuliers dans cette méthode, car nous effectuons des choses spéciales pour les valeurs des listes de sélection, les références, les dates et les éléments non-champs. Dans un cas typique, pour un élément de présentation reposant sur un champ autre que date, nous extrayons les propriétés displayValue et value à partir de l'entrée correspondante dans les données d'enregistrement JSON.
} else if (record.fields[compValue]) {
        var displayValue = record.fields[compValue].displayValue;
        let rawValue = record.fields[compValue].value;
        if (displayValue == null && rawValue != null) {
          displayValue = rawValue.toString();
        }
        values.push(
          {displayValue: displayValue,
           value: rawValue,
           label:component.label,
           field:compValue,
           fieldInfo,
           picklistUrl,
           editableForNew:item.editableForNew,
           editableForUpdate:item.editableForUpdate,
           isNull:displayValue == null})

Rendu des composants de présentation

Comme nous l'avons vu, l'objet renvoyé depuis recordLayout.getLayoutModel() est enregistré dans l'état global comme state.record.record. Cet état est utilisé pour rendre les composants correspondants dans l'IU. Le conteneur de niveau supérieur RecordViewerWrapper.js vérifie si state.record.record est disponible, et le transmet en aval à un composant intégré RecordViewer.js dans la propriété record. Intégrés dans le composant RecordViewer.js, RecordSection.js et RecordRow.js affichent leurs sections et lignes.

Observez particulièrement RecordRow.jsgetViewItemCells(). Lorsque nous rendons chaque cellule de la ligne, le chemin crée un <div> pour chaque composant de l'élément. Nous fournissons la clé à <div> car React en a besoin. Nous utilisons displayValue pour rendre le texte que vous voyez à l'écran.
{ item.values.map((component, i) => {
             if (component.displayValue && component.displayValue.length > 0) {
               if (component.fieldInfo.htmlFormatted) {
                 return (
                   <div key={'component' + itemLabel + ',' + i} dangerouslySetInnerHTML={{__html: component.displayValue}}></div>
                 )
               } else {
                 return (
                   <div key={'component' + itemLabel + ',' + i}>{component.displayValue}</div>
                 )
               }
             } else {
               return null
             }
           }
          )}

Le résultat est que notre application est actionnée dynamiquement par la présentation et les informations de l'objet renvoyées par l'API d'IU. Au lieu de coder en dur les champs et les positions des champs dans la présentation, utilisez l'API d'IU pour construire une IU en mesure de se réorganiser lorsqu'un administrateur met à jour les présentations et les objets dans Salesforce.