Oracle JET仮想DOMアプリケーションのデータ・レコードの更新

はじめに

このチュートリアルでは、Oracle JavaScript Extension Toolkit (Oracle JET)仮想DOMアプリケーションを使用して、既存のデータ・レコードを更新し、RESTサービスに送信する方法を示します。

目的

このチュートリアルでは、既存のデータ・レコードを更新してRESTサービスに送信する方法を学習します。

前提条件

タスク1: フォーム情報を管理するためのコンポーネントの作成

レコードを更新する機能を起動するダイアログを表示する新規コンポーネントを作成します。

  1. JET-Virtual-DOM-app/src/components/ActivityItemディレクトリに移動し、新しいEditItemDialog.tsxファイルを作成してエディタで開きます。

  2. 新しいコンポーネントのファンクション名(EditItemDialog)を定義するプレースホルダ・エントリを追加します。

    import { h } from "preact";
    
    type Props = {
      message?: string;
    };
    
    const EditItemDialog = (props: Props) => {
      return (
        <div class="oj-web-applayout-max-width oj-web-applayout-content">
          <p>content</p>
        </div>
      );
    };
    
    export default EditItemDialog;
    

タスク2: ダイアログを開く処理

ItemActionsContainerコンポーネントでタイプおよび関数を宣言し、レコードを更新する機能を含むEditItemDialogコンポーネントを起動します。

  1. JET-Virtual-DOM-app/src/components/ActivityItemディレクトリに移動し、ItemActionsContainer.tsxファイルを開きます。

  2. ファイルの上部で、useStateおよびuseEffect Preactフックをインポートし、EditItemDialogコンポーネントを使用するために必要なProps型の別名に追加のプロパティを定義してから、Item型の別名を定義します。

     import { h } from "preact";
     import "ojs/ojbutton";
     import { useState, useEffect } from "preact/hooks";
    
     type Props = {
         create: () => void;
         edit: () => void;
         itemSelected: Partial<Item>;
     };
    
     type Item = {
         id: number;
         name: string;
         short_desc?: string;
         price?: number;
         quantity?: number;
         quantity_shipped?: number;
         quantity_instock?: number;
         activity_id?: number;
         image?: string;
     };
    
  3. return文の前に、インポートしたPreactフックを使用して、アクティビティ・アイテムが選択されているかどうかを確認します。

     const ItemActionsContainer = (props: Props) => {
         const [hideActions, setHideActions] = useState<boolean>(true);
    
             if (props.itemSelected?.id) {
         console.log("Selected: " + JSON.stringify(props.itemSelected));
         }
    
         useEffect(() => {
         if (props.itemSelected?.id) {
             setHideActions(false);
         } else {
             setHideActions(true);
         }
         }, [props.itemSelected]);
    
         return (
    
    
  4. return文で、editプロパティを参照するonojAction属性を持つ新しいoj-button要素を追加します。

    const ItemActionsContainer = (props: Props) => {
     return (
       <div>
         <oj-button id="createButton" onojAction={props.create}>Create</oj-button>
         <oj-button id="updateButton" disabled={hideActions} onojAction={props.edit}>Update</oj-button>
       </div>
    

    ItemActionsContainer.tsxファイルを保存します。コードはItemActionsContainer.tsx.txtのようになります。

  5. EditItemDialog.tsxファイルの上部で、Oracle JETダイアログ・コンポーネントのモジュール、およびuseRefuseEffectMutableRefおよびuseState Preactフックのモジュールをインポートします。

    import { h } from "preact";
    import { useRef, useEffect, useState, MutableRef  } from "preact/hooks";
    import "ojs/ojdialog";
    import { ojDialog } from "ojs/ojdialog";
    
  6. Props型の別名で、次のプロパティを作成します。

    type Props = {
       isOpened: boolean;
       closeDialog: (ref: MutableRef<ojDialog>, type: string) => void;
       editItem: (data: Partial<Item>, ref: MutableRef<ojDialog>) => void;
       itemData: Partial<Item>;
     };
    
  7. return文で、既存のdiv要素を、oj-dialogカスタム要素をラップするspan要素に置き換えます。

     return (
         <span>
         <oj-dialog id="editDialog" ref={editDialogRef as MutableRef<ojDialog>} 
                     dialogTitle="Update Item Details" onojClose={closeDialog} cancelBehavior="icon">
             <div slot="body">
             <oj-label-value labelEdge="inside">
                 <oj-label for="itemid" slot="label">
                 Item ID
                 </oj-label>
                 <div id="itemid" slot="value" class="slot-line">
                 {editFormData?.id}
                 </div>
             </oj-label-value>
         <oj-form-layout>
             <oj-input-text id="name" labelHint="Name" onvalueChanged={onChangeHandler} value={editFormData?.name}></oj-input-text>
             <oj-input-text id="price" labelHint="Price" onvalueChanged={onChangeHandler} value={editFormData?.price}></oj-input-text>
             <oj-input-text id="short_desc" labelHint="Description" 
                         onvalueChanged={onChangeHandler} value={editFormData?.short_desc}></oj-input-text>
             </oj-form-layout>
             </div>
             <div slot="footer">
             <oj-button id="submitBtn" onojAction={editItem}>
                 Submit
             </oj-button>
             </div>
         </oj-dialog>
     </span>
     );
    
  8. return文の前に、属性値がoj-dialogカスタム要素参照の子カスタム要素にあるメソッドを追加します。たとえば、onChangeHandlerメソッドは、oj-input-textコンポーネントがonvalueChanged属性を使用して変更を検出したときにコールされます。

     const EditItemDialog = (props: Props) => {
         const editDialogRef = useRef<ojDialog>();
         const [editFormData, setEditFormData] = useState<Partial<Item>>({});
    
         const onChangeHandler = (event: any) => {
         if (event.detail.updatedFrom === "internal") {
             setEditFormData({
             ...editFormData,
             [event.currentTarget.id]: event.detail.value,
             });
         }
         };
    
         const closeDialog = () => {
         props.closeDialog(editDialogRef as MutableRef<ojDialog>, "edit");
         };
    
         const editItem = () => {
         console.log("data: " + JSON.stringify(editFormData));
         props.editItem(editFormData, editDialogRef as MutableRef<ojDialog>);
         };
    
         useEffect(() => {
         setEditFormData(props.itemData);
         props.isOpened ? editDialogRef.current?.open() : editDialogRef.current?.close();
         }, [props.isOpened]);
    
         return (
    
    
  9. EditItemDialog関数の宣言の前に、更新してRESTサービスに送信するデータのフィールドを含むItem型の別名を定義します。

    type Item = {
      id: number;
      name: string | undefined;
      short_desc?: string;
      price?: number;
      quantity?: number;
      quantity_shipped?: number;
      quantity_instock?: number;
      activity_id?: number;
      image?: string;
     };
    
     const EditItemDialog = (props: Props) => {
    

    EditItemDialog.tsxファイルを保存します。コードはEditItemDialog.tsx.txtのようになります。

タスク3: EditItemDialogコンポーネントの消費

  1. ActivityItemContainer.tsxファイルを開き、最後のタスクで作成したEditItemDialogコンポーネントに加えて、PreactのMutableRefフックと、DialogコンポーネントのOracle JETモジュールをインポートします。

     import { useState, useCallback, MutableRef, useRef } from "preact/hooks";
     import EditItemDialog from "./EditItemDialog";
    
  2. Props型の別名で、dataのエントリを更新してRESTDataProviderany型をサポートし、コンポーネントで使用されなくなったActivityItem型を削除またはコメント・アウトします。

     type Props = {
       data?: RESTDataProvider<any, any>;
       selectedActivity: Item | null;
      	  onItemChanged: (item: Item) => void;
     };
    
    // type ActivityItem = {
     //   id: number;
     //   name: string;
     //   items: Array<Item>;
     //   short_desc: string;
     //   image: string;
     // };
    
  3. return文で、ItemActionsContainer要素をitemSelectedおよびedit属性値で更新します。CreateNewItemDialog要素の後に、インポートしたEditItemDialogコンポーネントに新しい要素を追加します。

     <div id="container">
         <h3>Activity Items</h3>
           <ItemActionsContainer create={openCreateDialog} itemSelected={activityItemValue} edit={openEditDialog} />
           . . . 
    </div>
     <CreateNewItemDialog isOpened={isCreateOpened} createNewItem={createItem} closeDialog={handleDialogClose} />
     <EditItemDialog isOpened={isEditOpened} editItem={editItem} closeDialog={handleDialogClose} itemData={itemData} />
      . . . 
    
  4. return文の前に、編集ダイアログを開くopenEditDialog関数と、更新されたアクティビティ・アイテムをRESTサービスに送信するeditItem関数を追加します。

     const openEditDialog = () => {
         console.log("Item: " + JSON.stringify(itemData));
         setIsEditOpened(true);
         console.log("Edit dialog opened");
         };
    
     const editItem = async (newItemData:Partial<Item>, editDialogRef = useRef<ojDialog>()) => {
         if (newItemData != null) {
         const row = {
             itemId: newItemData.id,
             name: newItemData.name,
             price: newItemData.price,
             short_desc: newItemData.short_desc,
         };
    
         // Create and send request to update row on rest service
         const request = new Request(`${restServerURLItems}${itemData.id}`, {
             headers: new Headers({
             "Content-type": "application/json; charset=UTF-8",
             }),
             body: JSON.stringify(row),
             method: "PUT",
         });
         const response = await fetch(request);
         const updatedRow = await response.json();
    
         // Create update mutate event and call mutate method
         // to notify dataprovider consumers that a row has been
         // updated
         const updatedRowKey = itemData.id;
         const updatedRowMetaData = { key: updatedRowKey };
         props.data?.mutate({
             update: {
             data: [updatedRow],
             keys: new Set([updatedRowKey]),
             metadata: [updatedRowMetaData],
             },
         });
         } // End if statement
         console.log("Edited item");
         editDialogRef.current?.close();
         };
    
    

    ActivityItemContainer.tsxファイルを保存します。コードはActivityItemContainer.tsx.txtのようになります。

タスク4: コードのテストおよびレコードの更新

  1. ターミナル・ウィンドウで、JET-Virtual-DOM-appディレクトリに移動し、仮想DOMアプリケーションを実行します。

     npx ojet serve
    
  2. ブラウザで、仮想DOMアプリケーションの動的変更を表示します。
  3. 仮想DOMアプリケーションで、Baseballアクティビティをクリックし、SureFire Ball (Set of 4)アイテムをクリックします。
  4. [更新]ボタンをクリックします。

    「品目詳細の更新」ダイアログ・ボックスが表示されます。

  5. 価格を20.5から21に変更し、「発行」をクリックします。

    セクションがリフレッシュされ、品目の価格が更新されました。

    品目詳細の更新

  6. 実行中の仮想DOMアプリケーションを表示するブラウザ・ウィンドウまたはタブを閉じます。
  7. ターミナル・ウィンドウでCtrl+Cを押し、プロンプトが表示されたら、yと入力してOracle JETツール・バッチ・ジョブを終了します。

次のステップ

このモジュールの次のチュートリアルに進みます。

このチュートリアルは、「RESTサービスを使用したCRUD操作」モジュールの一部です。

仮想DOM学習パスのメイン・ページに戻ると、仮想DOMアプリケーションの構築に関するすべてのモジュールにアクセスできます。

その他の学習リソース

docs.oracle.com/learnで他のラボを確認するか、Oracle Learning YouTubeチャネルで無料のラーニング・コンテンツにアクセスしてください。また、education.oracle.com/learning-explorerにアクセスして、Oracle Learning Explorerになります。

製品ドキュメントについては、Oracle Help Centerを参照してください。