Recuperación de datos de una API de REST en una aplicación DOM virtual de Oracle JET

Introducción

En este tutorial se muestra cómo acceder a un servicio REST, integrarlo en la aplicación DOM virtual de Oracle JavaScript Extension Toolkit (Oracle JET) y enlazar los datos a una vista de lista en la interfaz de usuario.

Objetivos

En este tutorial, aprenderá a crear instancias de la clase RESTDataProvider. Esta clase representa los datos disponibles de los servicios REST basados en JSON.

Requisitos

Tarea 1: Descarga la aplicación Starter Virtual DOM

Omita esta tarea si continúa trabajando en una aplicación que creó en la ruta de aprendizaje anterior.

  1. Cambie el nombre de jet-virtual-dom-app-temp.zip a JET-Virtual-DOM-app.zip. Extraiga el contenido al directorio JET-Virtual-DOM-app.

  2. Navegue al directorio JET-Virtual-DOM-app y restaure la aplicación DOM virtual de Oracle JET.

    npm install
    

    La aplicación DOM virtual está lista para usar.

Tarea 2: Acceso al servicio REST

Haga clic en el enlace Apex para ver los datos de REST para el punto final del recurso Actividades.

Los datos contienen una lista de actividades con varios atributos.

{
  "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/"
      },
      . . .
   ]
}

Familiarícese con los datos y las propiedades que devuelve el punto final. Tendrá que comprender estos detalles al crear una instancia de RESTDataProvider más adelante en este tutorial. Tenga en cuenta, por ejemplo, cómo el punto final devuelve una propiedad items que hace referencia a una serie de actividades individuales.

Tarea 3: Creación de un proveedor de datos para recuperar datos de actividad

  1. Navegue hasta el directorio JET-Virtual-DOM-app/src/components/ y abra el archivo ParentContainer1.tsx en un editor.

  2. Al principio del archivo ParentContainer1.tsx, importe el módulo RESTDataProvider y suprima o comente las sentencias de importación para el módulo MutableArrayDataProvider y el archivo store_data.json.

    También importamos el enlace useMemo que utilizaremos al crear RESTDataProvider más adelante.

    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. Cree una variable keyattributes y una variable restServerURLActivities que haga referencia al atributo de clave de actividad y al punto final de REST que transferirá a la instancia RESTDataProvider que creará en el siguiente paso.

    let keyAttributes: string = 'id';
    // REST endpoint that returns Activity data
    const restServerURLActivities: string =
      'https://apex.oracle.com/pls/apex/oraclejet/lp/activities/';
    
  4. Cree una nueva variable activityDataProvider que haga referencia al módulo RESTDataProvider y suprima o comente la variable activityDataProvider preexistente que haga referencia al módulo MutableArrayDataProvider.

    Creamos la nueva variable activityDataProvider en la función ParentContainer1 y la encapsulamos en un enlace useMemo para garantizar que la instancia del proveedor de datos se vuelva a crear solo si los datos del proveedor de datos realmente cambian.

    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 };
          },
          },
       },
     }), [])
    . . .
    

    Nota: La función response anterior que extrae datos y otras propiedades del cuerpo de respuesta del punto final debe devolver un objeto con una propiedad data. Dado que el punto final con el que trabajamos devuelve una propiedad items, asignamos esta última propiedad a data en la función de respuesta.

  5. Guarde el archivo ParentContainer1.tsx.

    El archivo ParentContainer1.tsx debe tener un aspecto similar a ParentContainer1-a.tsx.txt.

  6. Navegue hasta el directorio JET-Virtual-DOM-app/src/components/Activity y abra el archivo ActivityContainer.tsx en un editor.

  7. Al principio del archivo ActivityContainer.tsx, importe el módulo RESTDataProvider y comente o suprima la sentencia de importación para el módulo MutableArrayDataProvider.

       import { h, ComponentProps } from "preact";
       . . .
       // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider");
       import { RESTDataProvider } from "ojs/ojrestdataprovider";
       . . .
    
    
  8. En el alias de tipo Props, modifique la propiedad opcional data para que haga referencia al tipo RESTDataProvider en lugar del tipo preexistente MutableArrayDataProvider<Activity["id"], Activity>.

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

    El archivo ActivityContainer.tsx debe tener un aspecto similar a ActivityContainer.tsx.txt.

Tarea 4: Adición de un manejador de errores para gestionar un fallo al recuperar datos

La instancia RESTDataProvider proporciona una opción de error que puede utilizar para llamar a una función de devolución de llamada cuando falla un intento de recuperar datos. Implantará esta capacidad en el caso de que falle un intento de recuperar la lista de actividades.

  1. En el archivo ParentContainer1.tsx del directorio JET-Virtual-DOM-app/src/components/, importe el enlace useRef de Preact.

    . . .
    import { RESTDataProvider } from "ojs/ojrestdataprovider";
    import { useState, useMemo, useRef } from "preact/hooks";
    . . .
    
  2. En la variable activityDataProvider que hace referencia a RESTDataProvider, agregue la opción error y una referencia a la función de devolución de llamada que llama (fetchErrorHandler).

    const ParentContainer1 = () => {
    
       const activityDataProvider = useMemo(() => new RESTDataProvider<Activity["id"], Activity>({
          keyAttributes: keyAttributes,
          url: restServerURLActivities,
          error: fetchErrorHandler,
          transforms: {
          . . .
    
  3. Antes de la variable activityDataProvider, agregue el código para fetchErrorHandler y los enlaces (useState y useRef) que utilizamos para determinar si el intento de recuperar datos se ha realizado correctamente.

    . . .
    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. En la sentencia return al final del archivo ParentContainer1.tsx, agregue una comprobación que determine si muestra la lista de actividades o un mensaje en caso de que se produzca un fallo en el intento de recuperar datos.

    . . .
    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. Guarde el archivo ParentContainer1.tsx.

    El archivo ParentContainer1.tsx debe tener un aspecto similar a ParentContainer1-b.tsx.txt.

Tarea 5: Creación de un proveedor de datos para recuperar datos de artículos

Utilice otra instancia RESTDataProvider para recuperar un subjuego de los datos, la lista de elementos para una actividad concreta. Para ello, debe proporcionar una nueva URL que contenga el ID de actividad seleccionado.

  1. Navegue hasta el directorio JET-Virtual-DOM-app/src/components/ y abra el archivo ParentContainer2.tsx en un editor.

  2. Al principio del archivo ParentContainer2.tsx, importe el módulo RESTDataProvider y suprima o comente las sentencias de importación para el módulo MutableArrayDataProvider y el archivo store_data.json. Importe también la interfaz TextFilter que utilizaremos al activar la capacidad de filtrado en la instancia RESTDataProvider que creamos.

    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. Después del alias de tipo Item, cree una variable baseServiceUrl para hacer referencia al punto final de REST que transferirá a la instancia de RESTDataProvider que creará en el siguiente paso.

    type Item = {
       . . .
     };
    
    const baseServiceUrl =
      "https://apex.oracle.com/pls/apex/oraclejet/lp/activities/";
    
  4. Cree una instancia inicial de RESTDataProvider que transferirá en los siguientes pasos a los enlaces useState y 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. Comente o suprima el código existente que ha creado una variable para leer datos del archivo store_data.json y que ha creado una instancia inicial 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. En la función ParentContainer2, sustituya el enlace useEffect existente que gestiona la instancia de MutableArrayDataProvider por una nueva definición que crea un RESTDataProvider para los elementos de actividad que corresponden al ID de actividad seleccionado. Esta nueva definición también incluye un filtro de texto para filtrar por el campo name del elemento de actividad.

    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. Guarde el archivo ParentContainer2.tsx.

    El archivo ParentContainer2.tsx debe tener un aspecto similar a ParentContainer2.tsx.txt.

  8. Navegue hasta el directorio JET-Virtual-DOM-app/src/components/ActivityItem y abra el archivo ActivityItemContainer.tsx en un editor.

  9. Al inicio del archivo ActivityItemContainer.tsx, importe el módulo RESTDataProvider y comente o suprima la sentencia de importación para el módulo MutableArrayDataProvider.

    import { h, ComponentProps } from "preact";
    . . .
    // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider");
    import { RESTDataProvider } from "ojs/ojrestdataprovider";
    . . .
    
  10. En el alias de tipo Props, modifique la propiedad data para que haga referencia al tipo RESTDataProvider en lugar del tipo preexistente MutableArrayDataProvider<Activity["id"], Activity>.

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

    El archivo ActivityItemContainer.tsx debe tener un aspecto similar a ActivityItemContainer.tsx.txt.

Tarea 6: Prueba de la aplicación DOM virtual

  1. En la ventana de terminal, cambie al directorio JET-Virtual-DOM-app y ejecute la aplicación DOM virtual.

    npx ojet serve
    
  2. En la ventana del explorador, vea los cambios dinámicos en la aplicación DOM virtual.

    Pantalla Registros recuperados

  3. Cierre la ventana o el separador del explorador que muestra la aplicación DOM virtual en ejecución.

  4. En la ventana de terminal, pulse Ctrl+C y, si se le solicita, introduzca y para salir del trabajo por lotes de herramientas de Oracle JET.

  5. En la ventana de terminal, ejecute la aplicación DOM virtual utilizando los siguientes argumentos de línea de comandos adicionales.

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

    En esta ocasión, la aplicación DOM virtual muestra el siguiente mensaje porque el servicio REST al que intenta acceder solo acepta solicitudes en el puerto de servidor que el comando ojet serve utiliza por defecto (8000), por lo que el intento de RESTDataProvider de recuperar del servicio REST ha fallado.

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

Siguiente paso

Continúe con el siguiente tutorial de este módulo.

Este tutorial forma parte del módulo Operaciones de CRM mediante un servicio REST.

Puede volver a la página principal de la ruta de aprendizaje de DOM virtual para acceder a todos los módulos de creación de aplicaciones de DOM virtuales.

Más recursos de aprendizaje

Explore otros laboratorios en docs.oracle.com/learn o acceda a más contenido de aprendizaje gratuito en el canal YouTube de Oracle Learning. Además, visite education.oracle.com/learning-explorer para convertirse en un explorador de Oracle Learning.

Para obtener documentación sobre el producto, visite Oracle Help Center.