Extraire des données à partir d'une API REST dans une application DOM virtuelle Oracle JET

Introduction

Ce tutoriel vous explique comment accéder à un service REST, l'intégrer à votre application DOM virtuelle Oracle JavaScript Extension Toolkit (Oracle JET), et lier des données à une vue de liste dans votre interface utilisateur.

Objectifs

Dans ce tutoriel, vous allez apprendre à créer des instances de la classe RESTDataProvider. Cette classe représente les données disponibles à partir des services REST basés sur JSON.

Prérequis

Tâche 1 : télécharger l'application Starter Virtual DOM

Ignorez cette tâche si vous continuez à travailler dans une application que vous avez créée dans le parcours de formation précédent.

  1. Renommez jet-virtual-dom-app-temp.zip en JET-Virtual-DOM-app.zip. Extrayez le contenu dans le répertoire JET-Virtual-DOM-app.

  2. Accédez au répertoire JET-Virtual-DOM-app et restaurez l'application DOM virtuelle Oracle JET.

    npm install
    

    L'application DOM virtuelle est prête à être utilisée.

Tâche 2 : accéder au service REST

Cliquez sur le lien Apex pour visualiser les données REST de l'adresse de ressource Activités.

Les données contiennent une liste d'activités avec différents attributs.

{
  "items": [
      {
      "id": 1,
      "name": "Baseball",
      "short_desc": "Equipment we carry for baseball players.",
      "image": "css/images/product_images/baseball.jpg"
      },
   . . .
   ],
   "hasMore": false,
   "limit": 25,
   "offset": 0,
   "count": 4,
   "links": [
      {
      "rel": "self",
      "href": "https://apex.oracle.com/pls/apex/oraclejet/lp/activities/"
      },
      . . .
   ]
}

Familiarisez-vous avec les données et les propriétés renvoyées par l'adresse. Vous devrez comprendre ces détails lorsque vous créerez une instance de RESTDataProvider plus tard dans ce tutoriel. Notez, par exemple, comment l'adresse renvoie une propriété items qui référence une série d'activités individuelles.

Tâche 3 : créer un fournisseur de données pour extraire les données d'activité

  1. Accédez au répertoire JET-Virtual-DOM-app/src/components/ et ouvrez le fichier ParentContainer1.tsx dans un éditeur.

  2. Au début du fichier ParentContainer1.tsx, importez le module RESTDataProvider et supprimez ou mettez en commentaire les instructions import pour le module MutableArrayDataProvider et le fichier store_data.json.

    Nous importons également le hook useMemo que nous utiliserons lors de la création de RESTDataProvider ultérieurement.

    import { h } from "preact";
    . . .
    // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider");
    // import * as storeData from "text!./store_data.json";
    import { RESTDataProvider } from "ojs/ojrestdataprovider";
    import { useState, useMemo } from "preact/hooks";
    . . .
    
  3. Créez une variable keyattributes et une variable restServerURLActivities qui référencent l'attribut de clé d'activité et l'adresse REST que vous allez transmettre à l'instance RESTDataProvider que vous allez créer à l'étape suivante.

    let keyAttributes: string = 'id';
    // REST endpoint that returns Activity data
    const restServerURLActivities: string =
      'https://apex.oracle.com/pls/apex/oraclejet/lp/activities/';
    
  4. Créez une variable activityDataProvider qui référence le module RESTDataProvider et supprimez ou mettez en commentaire la variable activityDataProvider préexistante qui référencait le module MutableArrayDataProvider.

    Nous créons la variable activityDataProvider dans la fonction ParentContainer1 et l'enveloppons dans un point d'accrochage (hook) useMemo pour nous assurer que l'instance de fournisseur de données est recréée uniquement si les données du fournisseur de données changent réellement.

    const ParentContainer1 = () => {
    
    const activityDataProvider = useMemo(() => new RESTDataProvider<Activity["id"], Activity>({
       keyAttributes: keyAttributes,
       url: restServerURLActivities,
       transforms: {
          fetchFirst: {
          request: async (options) => {
             const url = new URL(options.url);
             const { size, offset } = options.fetchParameters;
             url.searchParams.set("limit", String(size));
             url.searchParams.set("offset", String(offset));
             return new Request(url.href);
          },
          response: async ({ body }) => {
             const { items, totalSize, hasMore } = body;
             return { data: items, totalSize, hasMore };
          },
          },
       },
     }), [])
    . . .
    

    Remarque : la fonction response ci-dessus qui extrait des données et d'autres propriétés du corps de réponse de l'adresse doit renvoyer un objet avec une propriété data. Etant donné que l'adresse avec laquelle nous travaillons renvoie une propriété items, nous affectons cette dernière propriété à data dans la fonction de réponse.

  5. Enregistrez le fichier ParentContainer1.tsx.

    Votre fichier ParentContainer1.tsx doit ressembler à ParentContainer1-a.tsx.txt.

  6. Accédez au répertoire JET-Virtual-DOM-app/src/components/Activity et ouvrez le fichier ActivityContainer.tsx dans un éditeur.

  7. Au début du fichier ActivityContainer.tsx, importez le module RESTDataProvider et mettez en commentaire ou supprimez l'instruction import pour le module MutableArrayDataProvider.

       import { h, ComponentProps } from "preact";
       . . .
       // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider");
       import { RESTDataProvider } from "ojs/ojrestdataprovider";
       . . .
    
    
  8. Dans l'alias de type Props, modifiez la propriété data facultative pour référencer le type RESTDataProvider au lieu du type préexistant MutableArrayDataProvider<Activity["id"], Activity>.

       type Props = {
          data?: RESTDataProvider<Activity["id"], Activity>;
          // data?: MutableArrayDataProvider<Activity["id"], Activity>;
       . . .
       };
    
  9. Enregistrez le fichier ActivityContainer.tsx.

    Votre fichier ActivityContainer.tsx doit ressembler à ActivityContainer.tsx.txt.

Tâche 4 : ajout d'un gestionnaire d'erreurs pour gérer l'échec d'extraction des données

L'instance RESTDataProvider fournit une option d'erreur que vous pouvez utiliser pour appeler une fonction de rappel lorsqu'une tentative d'extraction de données échoue. Vous allez implémenter cette fonctionnalité pour le scénario dans lequel une tentative d'extraction de la liste des activités échoue.

  1. Dans le fichier ParentContainer1.tsx à partir du répertoire JET-Virtual-DOM-app/src/components/, importez le hook useRef à partir de Preact.

    . . .
    import { RESTDataProvider } from "ojs/ojrestdataprovider";
    import { useState, useMemo, useRef } from "preact/hooks";
    . . .
    
  2. Dans la variable activityDataProvider qui référence RESTDataProvider, ajoutez l'option error et une référence à la fonction de rappel qu'elle appelle (fetchErrorHandler).

    const ParentContainer1 = () => {
    
       const activityDataProvider = useMemo(() => new RESTDataProvider<Activity["id"], Activity>({
          keyAttributes: keyAttributes,
          url: restServerURLActivities,
          error: fetchErrorHandler,
          transforms: {
          . . .
    
  3. Avant la variable activityDataProvider, ajoutez le code pour fetchErrorHandler et les points d'ancrage (useState et useRef) que nous utilisons pour déterminer si la tentative d'extraction des données a réussi.

    . . .
    const ParentContainer1 = () => {
    
    const [fetchStatus, setFetchStatus] = useState(true);
    const fetchError = useRef<string>();
    
    const fetchErrorHandler = (errorDetail: RESTDataProvider.FetchErrorDetail<number, Activity> |
                                            RESTDataProvider.FetchResponseErrorDetail<number, Activity>) => {
       setFetchStatus(false);
       if (errorDetail.hasOwnProperty('response')) {
          fetchError.current = `${(errorDetail as RESTDataProvider.FetchResponseErrorDetail<number, Activity>).response.status}`;
       }
       else {
          fetchError.current = (errorDetail as RESTDataProvider.FetchErrorDetail<number, Activity>).error.message;
       }
    }
    
    const activityDataProvider = new RESTDataProvider<Activity["id"], Activity>({
    . . .
    
  4. Dans l'instruction return à la fin du fichier ParentContainer1.tsx, ajoutez une vérification qui détermine si vous affichez la liste des activités ou un message en cas d'échec de la tentative d'extraction des données.

    . . .
    return (
       <div>
          {fetchStatus ? (
          <div id="parentContainer1" class="oj-flex oj-flex-init">
             <ActivityContainer data={activityDataProvider} onActivityChanged={activityChangedHandler} />
             {showActivityItems() && (<ParentContainer2 activity={selectedActivity} />)}
             {!showActivityItems() && (<h4 class="oj-typography-subheading-sm">Select activity to view items</h4>)}
          </div>) :
          (<p>Sorry that we couldn't get your product information right now. Please contact your system administrator.</p>
          )}
       </div>
    );
    };
    
    export default ParentContainer1;
    
  5. Enregistrez le fichier ParentContainer1.tsx.

    Votre fichier ParentContainer1.tsx doit ressembler à ParentContainer1-b.tsx.txt.

Tâche 5 : créer un fournisseur de données pour extraire les données d'élément

Utilisez une autre instance RESTDataProvider pour extraire un sous-ensemble de données, la liste des éléments d'une activité particulière. Pour ce faire, indiquez une nouvelle URL contenant l'ID activité sélectionné.

  1. Accédez au répertoire JET-Virtual-DOM-app/src/components/ et ouvrez le fichier ParentContainer2.tsx dans un éditeur.

  2. Au début du fichier ParentContainer2.tsx, importez le module RESTDataProvider et supprimez ou mettez en commentaire les instructions import pour le module MutableArrayDataProvider et le fichier store_data.json. Importez également l'interface TextFilter que nous utiliserons lorsque nous activerons la fonctionnalité de filtrage dans l'instance RESTDataProvider que nous créerons.

    import { h } from "preact";
    . . .
    import { RESTDataProvider } from "ojs/ojrestdataprovider";
    import { TextFilter } from "ojs/ojdataprovider";
    
    // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider");
    // import * as storeData from "text!./store_data.json";
    . . .
    
    
  3. Après l'alias de type Item, créez une variable baseServiceUrl pour référencer l'adresse REST que vous allez transmettre à l'instance de RESTDataProvider que vous allez créer à l'étape suivante.

    type Item = {
       . . .
     };
    
    const baseServiceUrl =
      "https://apex.oracle.com/pls/apex/oraclejet/lp/activities/";
    
  4. Créez une instance initiale de RESTDataProvider que vous allez transmettre dans les étapes suivantes aux hooks useState et useEffect Preact.

       const baseServiceUrl = 'https://apex.oracle.com/pls/apex/oraclejet/lp/activities/';
    
       let INIT_DATAPROVIDER = new RESTDataProvider<ActivityItem['id'], ActivityItem>({
       keyAttributes: 'id',
       url: baseServiceUrl,
       transforms: {
          fetchFirst: {
             request: null!,
             response: (): any => {
             return { data: [] };
             },
          },
       },
       });
    
  5. Mettez en commentaire ou supprimez le code préexistant qui a créé une variable pour lire les données du fichier store_data.json et qui a créé une instance initiale de MutableArrayDataProvider.

       // const activityData = JSON.parse(storeData);
       // let activityItemsArray = activityData[0].items;
    
       // // Create data provider instance for the array of activity items for the selected activity
       // const INIT_DATAPROVIDER = new MutableArrayDataProvider<ActivityItem["id"], ActivityItem>(activityItemsArray, {
       //   keyAttributes: "id",
       // })
    
  6. Dans la fonction ParentContainer2, remplacez le point d'accrochage useEffect existant qui gère l'instance de MutableArrayDataProvider par une nouvelle définition qui crée une valeur RESTDataProvider pour les éléments d'activité correspondant à l'ID d'activité sélectionné. Cette nouvelle définition inclut également un filtre de texte à filtrer sur le champ name de l'élément d'activité.

    const ParentContainer2 = (props: Props) => {
    . . .
    useEffect(() => {
       setactivityItemDP(
          new RESTDataProvider<ActivityItem["id"], ActivityItem>({
          keyAttributes: "id",
          capabilities: {
             filter: {
                textFilter: true,
             },
          },
          url: baseServiceUrl + "/" + props.activity?.id + "/items/",
          textFilterAttributes: ["name"],
          transforms: {
             fetchFirst: {
                request: async (options) => {
                const url = new URL(options.url);
                const { size, offset } = options.fetchParameters;
                url.searchParams.set("limit", String(size));
                url.searchParams.set("offset", String(offset));
                const filterCriterion = options.fetchParameters
                   .filterCriterion as TextFilter<Item>;
                const { textFilterAttributes } = options.fetchOptions;
                if (
                   filterCriterion &&
                   filterCriterion.text &&
                   textFilterAttributes
                ) {
                   const { text } = filterCriterion;
                   textFilterAttributes.forEach((attribute) => {
                      url.searchParams.set(attribute, text);
                   });
                }
    
                return new Request(url.href);
                },
                response: async ({ body }) => {
                const { items, totalSize, hasMore } = body;
                return { data: items, totalSize, hasMore };
                },
             },
          },
          })
       );
    }, [props.activity]);
    
    return (
    . . .
    
  7. Enregistrez le fichier ParentContainer2.tsx.

    Votre fichier ParentContainer2.tsx doit se présenter comme suit : ParentContainer2.tsx.txt.

  8. Accédez au répertoire JET-Virtual-DOM-app/src/components/ActivityItem et ouvrez le fichier ActivityItemContainer.tsx dans un éditeur.

  9. Au début du fichier ActivityItemContainer.tsx, importez le module RESTDataProvider et commentez ou supprimez l'instruction import pour le module MutableArrayDataProvider.

    import { h, ComponentProps } from "preact";
    . . .
    // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider");
    import { RESTDataProvider } from "ojs/ojrestdataprovider";
    . . .
    
  10. Dans l'alias de type Props, modifiez la propriété data pour référencer le type RESTDataProvider au lieu du type préexistant MutableArrayDataProvider<Activity["id"], Activity>.

    type Props = {
      // data?: MutableArrayDataProvider<ActivityItem["id"], ActivityItem>;
      data?: RESTDataProvider<ActivityItem['id'], ActivityItem>;
      selectedActivity: Item | null;
      onItemChanged: (item: Item) => void;
    };
    
  11. Enregistrez le fichier ActivityItemContainer.tsx.

    Votre fichier ActivityItemContainer.tsx doit ressembler à ActivityItemContainer.tsx.txt.

Tâche 6 : tester l'application Virtual DOM

  1. Dans la fenêtre de terminal, accédez au répertoire JET-Virtual-DOM-app et exécutez l'application DOM virtuelle.

    npx ojet serve
    
  2. Dans la fenêtre du navigateur, affichez les modifications dynamiques dans votre application DOM virtuelle.

    Ecran Enregistrements extraits

  3. Fermez la fenêtre ou l'onglet du navigateur qui affiche votre application DOM virtuelle en cours d'exécution.

  4. Dans la fenêtre de terminal, appuyez sur Ctrl+C et, si vous y êtes invité, entrez y pour quitter le traitement batch des outils Oracle JET.

  5. Dans la fenêtre de terminal, exécutez l'application DOM virtuelle à l'aide des arguments de ligne de commande supplémentaires suivants.

    npx ojet serve --server-port=8144 --livereload-port=8145
    

    A cette occasion, l'application DOM virtuelle affiche le message suivant car le service REST auquel elle accède accepte uniquement les demandes sur le port de serveur que la commande ojet serve utilise par défaut (8000). Par conséquent, la tentative d'extraction du service REST par RESTDataProvider a échoué.

    Sorry that we couldn't get your product information right now. Please contact your system administrator.
    

Etape suivante

Passez au tutoriel suivant de ce module.

Ce tutoriel fait partie du module Opérations CRUD à l'aide d'un service REST.

Vous pouvez revenir à la page principale du parcours de formation DOM virtuel pour accéder à tous les modules sur la création d'applications DOM virtuelles.

Ressources de formation supplémentaires

Explorez d'autres ateliers sur le site docs.oracle.com/learn ou accédez à d'autres contenus d'apprentissage gratuits sur le canal Oracle Learning YouTube. En outre, visitez le site education.oracle.com/learning-explorer pour devenir un explorateur Oracle Learning.

Pour obtenir de la documentation sur le produit, consultez Oracle Help Center.