Daten aus einer REST-API in einer virtuellen Oracle JET-DOM-App abrufen

Einführung

In diesem Tutorial erfahren Sie, wie Sie auf einen REST-Service zugreifen, ihn in Ihre virtuelle DOM-App von Oracle JavaScript Extension Toolkit (Oracle JET) integrieren und Daten an eine Listenansicht in Ihrer Benutzeroberfläche binden.

Ziele

In diesem Tutorial erfahren Sie, wie Sie Instanzen der Klasse RESTDataProvider erstellen. Diese Klasse stellt Daten dar, die über JSON-basierte REST-Services verfügbar sind.

Voraussetzungen

Aufgabe 1: Laden Sie die Starter Virtual DOM App herunter

Überspringen Sie diese Aufgabe, wenn Sie weiterhin in einer App arbeiten, die Sie im vorherigen Lernpfad erstellt haben.

  1. Benennen Sie jet-virtual-dom-app-temp.zip in JET-Virtual-DOM-app.zip um. Extrahieren Sie den Inhalt in das JET-Virtual-DOM-app-Verzeichnis.

  2. Navigieren Sie zum Verzeichnis JET-Virtual-DOM-app, und stellen Sie die virtuelle Oracle JET-DOM-App wieder her.

    npm install
    

    Die virtuelle DOM-App ist einsatzbereit.

Aufgabe 2: Auf den REST-Service zugreifen

Klicken Sie auf den Pex-Link, um die REST-Daten für den Ressourcenendpunkt "Aktivitäten" anzuzeigen.

Die Daten enthalten eine Liste von Aktivitäten mit verschiedenen Attributen.

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

Machen Sie sich mit den Daten und den Eigenschaften vertraut, die der Endpunkt zurückgibt. Sie müssen diese Details verstehen, wenn Sie später in diesem Tutorial eine Instanz von RESTDataProvider erstellen. Beispiel: Wie der Endpunkt eine Eigenschaft items zurückgibt, die eine Reihe einzelner Aktivitäten referenziert.

Aufgabe 3: Datenprovider zum Abrufen von Aktivitätsdaten erstellen

  1. Navigieren Sie zum Verzeichnis JET-Virtual-DOM-app/src/components/, und öffnen Sie die Datei ParentContainer1.tsx in einem Editor.

  2. Importieren Sie am Anfang der Datei ParentContainer1.tsx das Modul RESTDataProvider, und löschen oder kommentieren Sie die Importanweisungen für das Modul MutableArrayDataProvider und die Datei store_data.json aus.

    Außerdem importieren wir den useMemo-Hook, den wir später beim Erstellen von RESTDataProvider verwenden werden.

    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. Erstellen Sie eine Variable keyattributes und eine Variable restServerURLActivities, die das Aktivitätsschlüsselattribut und den REST-Endpunkt referenziert, den Sie an die Instanz RESTDataProvider übergeben, die Sie im nächsten Schritt erstellen.

    let keyAttributes: string = 'id';
    // REST endpoint that returns Activity data
    const restServerURLActivities: string =
      'https://apex.oracle.com/pls/apex/oraclejet/lp/activities/';
    
  4. Erstellen Sie eine neue Variable activityDataProvider, die das Modul RESTDataProvider referenziert, und löschen oder kommentieren Sie die bereits vorhandene Variable activityDataProvider aus, die das Modul MutableArrayDataProvider referenziert.

    Die neue Variable activityDataProvider wird in der Funktion ParentContainer1 erstellt. Sie wird in einen useMemo-Hook eingeschlossen, um sicherzustellen, dass die Datenproviderinstanz nur dann neu erstellt wird, wenn sich die Daten im Datenprovider tatsächlich ändern.

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

    Hinweis: Die oben genannte Funktion response, mit der Daten und andere Eigenschaften aus dem Endpunktantwortbody extrahiert werden, muss ein Objekt mit einer Eigenschaft data zurückgeben. Da der Endpunkt, mit dem wir arbeiten, eine Eigenschaft items zurückgibt, weisen wir diese Eigenschaft data in der Antwortfunktion zu.

  5. Speichern Sie die Datei ParentContainer1.tsx.

    Die Datei ParentContainer1.tsx sollte ungefähr wie die Datei ParentContainer1-a.tsx.txt aussehen.

  6. Navigieren Sie zum Verzeichnis JET-Virtual-DOM-app/src/components/Activity, und öffnen Sie die Datei ActivityContainer.tsx in einem Editor.

  7. Importieren Sie am Anfang der Datei ActivityContainer.tsx das Modul RESTDataProvider, und kommentieren Sie die Importanweisung für das Modul MutableArrayDataProvider aus, oder löschen Sie sie.

       import { h, ComponentProps } from "preact";
       . . .
       // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider");
       import { RESTDataProvider } from "ojs/ojrestdataprovider";
       . . .
    
    
  8. Ändern Sie im Typalias Props die optionale Eigenschaft data, um den Typ RESTDataProvider anstelle des bereits vorhandenen Typs MutableArrayDataProvider<Activity["id"], Activity> zu referenzieren.

       type Props = {
          data?: RESTDataProvider<Activity["id"], Activity>;
          // data?: MutableArrayDataProvider<Activity["id"], Activity>;
       . . .
       };
    
  9. Speichern Sie die Datei ActivityContainer.tsx.

    Die ActivityContainer.tsx-Datei sollte ungefähr wie ActivityContainer.tsx.txt aussehen.

Aufgabe 4: Fehler-Handler hinzufügen, um Fehler beim Abrufen von Daten zu verwalten

Die Instanz RESTDataProvider bietet eine Fehleroption, mit der Sie eine Callback-Funktion aufrufen können, wenn ein Versuch, Daten abzurufen, nicht erfolgreich ist. Sie implementieren diese Funktion für das Szenario, in dem ein Versuch, die Liste der Aktivitäten abzurufen, nicht erfolgreich ist.

  1. Importieren Sie in der Datei ParentContainer1.tsx aus dem Verzeichnis JET-Virtual-DOM-app/src/components/ den useRef-Hook aus Preact.

    . . .
    import { RESTDataProvider } from "ojs/ojrestdataprovider";
    import { useState, useMemo, useRef } from "preact/hooks";
    . . .
    
  2. Fügen Sie in der Variablen activityDataProvider, die RESTDataProvider referenziert, die Option error und eine Referenz auf die Callback-Funktion hinzu, die sie aufruft (fetchErrorHandler).

    const ParentContainer1 = () => {
    
       const activityDataProvider = useMemo(() => new RESTDataProvider<Activity["id"], Activity>({
          keyAttributes: keyAttributes,
          url: restServerURLActivities,
          error: fetchErrorHandler,
          transforms: {
          . . .
    
  3. Fügen Sie vor der Variablen activityDataProvider den Code für fetchErrorHandler und die Hooks (useState und useRef) hinzu, mit denen bestimmt wird, ob der Versuch, Daten abzurufen, erfolgreich war.

    . . .
    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. Fügen Sie in der Return-Anweisung am Ende der Datei ParentContainer1.tsx eine Prüfung hinzu, die festlegt, ob die Liste der Aktivitäten angezeigt wird, oder eine Meldung, falls der Versuch, Daten abzurufen, nicht erfolgreich war.

    . . .
    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. Speichern Sie die Datei ParentContainer1.tsx.

    Die Datei ParentContainer1.tsx sollte ungefähr wie die Datei ParentContainer1-b.tsx.txt aussehen.

Aufgabe 5: Datenprovider zum Abrufen von Artikeldaten erstellen

Verwenden Sie eine andere RESTDataProvider-Instanz, um eine Teilmenge der Daten abzurufen, die Liste der Elemente für eine bestimmte Aktivität. Dazu geben Sie eine neue URL an, die die ausgewählte Aktivitäts-ID enthält.

  1. Navigieren Sie zum Verzeichnis JET-Virtual-DOM-app/src/components/, und öffnen Sie die Datei ParentContainer2.tsx in einem Editor.

  2. Importieren Sie am Anfang der Datei ParentContainer2.tsx das Modul RESTDataProvider, und löschen oder kommentieren Sie die Importanweisungen für das Modul MutableArrayDataProvider und die Datei store_data.json aus. Importieren Sie auch die Schnittstelle TextFilter, die verwendet wird, wenn die Filterfunktion in der von uns erstellten Instanz RESTDataProvider aktiviert wird.

    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. Erstellen Sie nach dem Alias des Typs Item eine Variable baseServiceUrl, um den REST-Endpunkt zu referenzieren, den Sie an die Instanz von RESTDataProvider übergeben, die Sie im nächsten Schritt erstellen.

    type Item = {
       . . .
     };
    
    const baseServiceUrl =
      "https://apex.oracle.com/pls/apex/oraclejet/lp/activities/";
    
  4. Erstellen Sie eine anfängliche Instanz der RESTDataProvider, die Sie in den folgenden Schritten an die Preact-Hooks useState und useEffect übergeben.

       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. Kommentieren Sie den bereits vorhandenen Code aus, der eine Variable zum Lesen von Daten aus der Datei store_data.json erstellt und eine anfängliche Instanz der Datei MutableArrayDataProvider erstellt hat, oder löschen Sie ihn.

       // 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. Ersetzen Sie in der Funktion ParentContainer2 den vorhandenen useEffect-Hook, der die Instanz von MutableArrayDataProvider verwaltet, durch eine neue Definition, die eine RESTDataProvider für die Aktivitätselemente erstellt, die der ausgewählten Aktivitäts-ID entsprechen. Diese neue Definition enthält auch einen Textfilter, um das Feld name des Aktivitätselements zu filtern.

    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. Speichern Sie die Datei ParentContainer2.tsx.

    Die Datei ParentContainer2.tsx sollte ungefähr wie ParentContainer2.tsx.txt aussehen.

  8. Navigieren Sie zum Verzeichnis JET-Virtual-DOM-app/src/components/ActivityItem, und öffnen Sie die Datei ActivityItemContainer.tsx in einem Editor.

  9. Importieren Sie am Anfang der Datei ActivityItemContainer.tsx das Modul RESTDataProvider, und kommentieren Sie die Importanweisung für das Modul MutableArrayDataProvider, oder löschen Sie sie.

    import { h, ComponentProps } from "preact";
    . . .
    // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider");
    import { RESTDataProvider } from "ojs/ojrestdataprovider";
    . . .
    
  10. Ändern Sie im Typalias Props die Eigenschaft data, um den Typ RESTDataProvider zu referenzieren, anstatt den bereits vorhandenen Typ MutableArrayDataProvider<Activity["id"], Activity>.

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

    Die ActivityItemContainer.tsx-Datei sollte ungefähr wie ActivityItemContainer.tsx.txt aussehen.

Aufgabe 6: Virtuelle DOM-App testen

  1. Wechseln Sie im Terminalfenster in das Verzeichnis JET-Virtual-DOM-app, und führen Sie die virtuelle DOM-App aus.

    npx ojet serve
    
  2. Zeigen Sie im Browserfenster die dynamischen Änderungen in Ihrer virtuellen DOM-App an.

    Fenster "Abgerufene Datensätze"

  3. Schließen Sie das Browserfenster oder die Registerkarte, in der die ausgeführte virtuelle DOM-App angezeigt wird.

  4. Drücken Sie im Terminalfenster Ctrl+C, und geben Sie bei entsprechender Aufforderung y ein, um den Batchjob für Oracle JET-Tooling zu beenden.

  5. Führen Sie im Terminalfenster die virtuelle DOM-App mit den folgenden zusätzlichen Befehlszeilenargumenten aus.

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

    Bei dieser Gelegenheit zeigt die virtuelle DOM-App die folgende Meldung an, da der REST-Service, auf den sie zugreifen möchte, nur Anforderungen auf dem Serverport akzeptiert, die der Befehl ojet serve standardmäßig verwendet (8000), sodass der Versuch von RESTDataProvider, aus dem REST-Service abzurufen, nicht erfolgreich war.

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

Nächsten Schritt

Fahren Sie mit dem nächsten Tutorial in diesem Modul fort.

Dieses Tutorial ist Teil des Moduls CRUD-Vorgänge mit einem REST-Service.

Sie können zur Hauptseite des virtuellen DOM-Lernpfads zurückkehren, um auf alle Module zum Erstellen virtueller DOM-Apps zuzugreifen.

Weitere Lernressourcen

Sehen Sie sich weitere Übungen zu docs.oracle.com/learn an, oder greifen Sie auf weitere kostenlose Lerninhalte im Oracle Learning YouTube-Kanal zu. Besuchen Sie außerdem education.oracle.com/learning-explorer, um ein Oracle Learning Explorer zu werden.

Die Produktdokumentation finden Sie im Oracle Help Center.