Oracle JETの仮想DOMアプリケーションにデータ・レコードを作成するためのフォームの作成

はじめに

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

目的

このチュートリアルでは、RESTサービスにデータを書き込む方法を学習します。

前提条件

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

新しいレコードを作成する機能を起動するために使用されるボタンを表示する新しいコンポーネントを作成します。ItemActionsContainerコンポーネントには、仮想DOMアプリケーション・ユーザーが新しいレコードを作成する機能を含むCreateNewItemDialogコンポーネントを起動できるボタンがあります。

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

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

    import { h } from 'preact';
    
    type Props = {
      message?: string;
    };
    
    const CreateNewItemDialog = (props: Props) => {
      return (
        <div class="oj-web-applayout-max-width oj-web-applayout-content">
          <p>content</p>
        </div>
      );
    };
    
    export default CreateNewItemDialog;
    
  3. 同じディレクトリで、ItemActionsContainer.tsxファイルを作成し、エディタで開きます。

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

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

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

Oracle JETモジュールをインポートし、Oracle JET仮想DOMアプリケーションがダイアログを正常に開くことを可能にする関数を宣言します。

  1. 開いているItemActionsContainer.tsxファイルの上部で、ボタン・コンポーネントのOracle JETモジュールをインポートします。

    import { h } from 'preact';
    import 'ojs/ojbutton';
    
  2. Propsタイプの別名でcreateプロパティを定義して、作成ダイアログを開くことを管理します。

    import { h } from 'preact';
    import 'ojs/ojbutton';
    
    type Props = {
      create: () => void;
    };
    
  3. return文で、既存のdiv要素を、createプロパティを参照するonojAction属性でoj-button要素をレンダリングする新しいdiv要素に置き換えます。

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

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

  4. 開いているCreateNewItemDialog.tsxファイルの上部で、ダイアログ・コンポーネントおよびMutableRefフックのOracle JETモジュールをインポートします。

    import { h } from 'preact';
    import 'ojs/ojdialog';
    import { ojDialog } from 'ojs/ojdialog';
    import { MutableRef } from 'preact/hooks';
    
  5. Props型の別名で、isOpenedおよびcloseDialogプロパティを定義します。

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

       return (
       <span>
          <oj-dialog id="createDialog" ref={createDialogRef} dialogTitle="Create New Item" onojClose={closeDialog} cancelBehavior="icon">
             <div slot="body">
             <p>dialog open</p>
             </div>
          </oj-dialog>
       </span>
       );
    
  7. CreateNewItemDialog.tsxファイルの上部に、useRefおよびuseEffect Preactフックをインポートします。

    import { h } from 'preact';
    import { useRef, useEffect } from 'preact/hooks';
    import 'ojs/ojdialog';
    import { ojDialog } from 'ojs/ojdialog';
    
  8. return文の前に、useRef Preactフックが取得する参照を保持するcreateDialogRef変数およびcloseDialog変数を宣言します。

    const CreateNewItemDialog = (props: Props) => {
    
       const createDialogRef = useRef<ojDialog>(null);
    
       const closeDialog = () => {
          props.closeDialog(createDialogRef as MutableRef<ojDialog>, "create");
        }
    
     return (
    	
    
  9. また、return文の前に、useEffectフックを使用して、isOpenedプロパティの値を設定する式を記述します。

     const CreateNewItemDialog = (props: Props) => {
         const createDialogRef = useRef<ojDialog>(null);
    
         const closeDialog = () => {
         props.closeDialog(createDialogRef as MutableRef<ojDialog>, "create");
         }
    
         useEffect(() => {
          props.isOpened
             ? createDialogRef.current?.open()
             : createDialogRef.current?.close();
         }, [props.isOpened]);
    
     return (
    
    

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

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

  11. ActivityItemContainer.tsxの上部で、作成したItemActionsContainerおよびCreateNewItemDialogコンポーネントをインポートし、Oracle JETフォーム・レイアウトおよび入力テキスト・コンポーネントのモジュールもインポートします。

    import ItemActionsContainer from "./ItemActionsContainer";
    import CreateNewItemDialog from "./CreateNewItemDialog";
    import "ojs/ojformlayout";
    import "ojs/ojinputtext";
    import { ojDialog } from "ojs/ojdialog";
    import { MutableRef} from "preact/hooks"
    
  12. ActivityItemContainer関数宣言の後、PreactのuseStateフックと関数(openCreateDialog)を使用してダイアログを開く変数を作成します。

    また、後のチュートリアルで作成した「編集」ダイアログのオープン状態を管理するエントリも含まれます。

    const ActivityItemContainer = (props: Props) => {
     const [isCreateOpened, setIsCreateOpened] = useState<boolean>(false);
     const [isEditOpened, setIsEditOpened] = useState<boolean>(false);
    
      const openCreateDialog = () => {
         console.log("CreateNewItemDialog called");
         setIsCreateOpened(true);
      };
    
  13. return文の前に、開いているダイアログを閉じる関数も含まれます。

    const handleDialogClose = (ref: MutableRef<ojDialog>, type: string) => {
       type === "create" ? setIsCreateOpened(false) : setIsEditOpened(false);
       ref.current.close();
    };
    
    return (
       <div id="activityItemsContainer" class=. . .>
    
  14. return文に、新しく作成されたItemActionsContainerおよびCreateNewItemDialogコンポーネントを含めます。

    return (
    <div id="activityItemsContainer" . . .>
     <div id="container">
       <h3>Activity Items</h3>
        <ItemActionsContainer create={openCreateDialog} />
        <CreateNewItemDialog isOpened={isCreateOpened} closeDialog={handleDialogClose} />
    

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

タスク3: ダイアログ入力の送信の処理

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

  2. 開いているCreateNewItemDialog.tsxファイルの上部に、PreactのuseStateフックをインポートします。

    import { ojDialog } from 'ojs/ojdialog';
    import { MutableRef, useRef, useEffect, useState } from "preact/hooks"
    
  3. Props型の別名で、createNewItemプロパティを定義します。

    type Props = {
         isOpened: boolean;
         closeDialog: (ref: MutableRef<ojDialog>, type: string) => void;
         createNewItem: (data: Partial<Item>, ref: MutableRef<ojDialog>) => void;
     };
    
  4. RESTサービスに送信するデータのフィールドを含むItemタイプの別名を定義します。

    type Item = {
      name?: string | undefined;
      short_desc?: string;
      price?: number;
      quantity_shipped?: number;
      quantity_instock?: number;
    };
    
  5. return文でoj-dialogカスタム要素を検索し、<div slot="body">の内容を入力フィールドのoj-form-layout要素およびoj-input-text要素に置き換えて、新しい項目を作成します。oj-button要素を含む<div slot="footer">も含まれます。

    <oj-dialog id="createDialog" ref={createDialogRef} dialogTitle="Create New Item" onojClose={closeDialog} cancelBehavior="icon">
        <div slot="body">
           <oj-form-layout>
           <oj-input-text id="name" labelHint="Name" onvalueChanged={onChangeHandler}></oj-input-text>
           <oj-input-text id="price" labelHint="Price" onvalueChanged={onChangeHandler}></oj-input-text>
           <oj-input-text id="short_desc" labelHint="Description" onvalueChanged={onChangeHandler}></oj-input-text>
           <oj-input-text id="quantity_instock" labelHint="Quantity: In-Stock" onvalueChanged={onChangeHandler}></oj-input-text>
           <oj-input-text id="quantity_shipped" labelHint="Quantity: Shipped" onvalueChanged={onChangeHandler}></oj-input-text>
           </oj-form-layout>
        </div>
        <div slot="footer">
           <oj-button id="submitBtn" onojAction={createItem}>Submit</oj-button>
        </div>
     </oj-dialog>
    
  6. return文の前に、useStateフックを使用し、Oracle JET要素が参照するonChangeHander関数およびcreateItem関数を含めます。

    const [formData, setFormData] = useState<Partial<Item>>({});
    
     const onChangeHandler = (event: any) => {
        setFormData({
           ...formData,
           [event.currentTarget.id]: event.detail.value,
        });
     }
    
     const createItem = () => {
        console.log("data: " + JSON.stringify(formData));
        props.createNewItem(formData, createDialogRef as MutableRef<ojDialog>);
     };
    
     return (
       <span>. . .
    

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

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

  8. return文で、CreateNewItemDialogクラスを更新して、CreateNewItemDialogコンポーネントで定義したcreateNewItemメソッドを含めます。

    <CreateNewItemDialog isOpened={isCreateOpened} createNewItem={createItem} closeDialog={handleDialogClose} />
    
  9. return文の前に、新しいアイテムを作成し、それをバックエンドRESTサービスに送信する新しいcreateItem関数を含めます。

    const createItem = async (data: Partial<Item>, createDialogRef: MutableRef<ojDialog>) => {
      //process create command and close dialog on success
      if (data?.name) {
         let quantity = Number(data.quantity_instock) + Number(data.quantity_shipped);
         const row = {
           name: data.name,
           short_desc: data.short_desc,
           price: data.price,
           quantity_instock: data.quantity_instock,
           quantity_shipped: data.quantity_shipped,
           quantity: quantity,
           activity_id: props.selectedActivity?.id,
           image: "css/images/product_images/jet_logo_256.png",
         };
    
         // Create and send request to REST service to add row
         const request = new Request(restServerURLItems, {
           headers: new Headers({
             "Content-type": "application/json; charset=UTF-8",
           }),
           body: JSON.stringify(row),
           method: "POST",
         });
    
         const response = await fetch(request);
         const addedRow = await response.json();
    
         activityItemDataProvider?.refresh();
         // Close dialog
         console.log("Created new item");
         createDialogRef.current.close();
       }
     };
    
  10. ActivityItemContainerファンクション宣言の後、アイテムをRESTサービスに送信するために使用するURLを参照する変数を定義します。

    const ActivityItemContainer = (props: Props) => {
        const activityItemDataProvider = props.data;
        const restServerURLItems = "https://apex.oracle.com/pls/apex/oraclejet/lp/activities/" + props.selectedActivity?.id + "/items/";
    
  11. ActivityItemContainer.tsxファイルを保存します。コードはActivityItemContainer-2.tsx.txtのようになります。

タスク4: コードのテストおよびレコードの作成

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

    npx ojet serve
    
  2. ブラウザで、仮想DOMアプリケーションの動的変更を表示します。
  3. 仮想DOMアプリケーションで、「Baseball」アクティビティをクリックします。
  4. 「作成」をクリックします。

    「新規アイテムの作成」ダイアログが開きます。

  5. 新規品目の詳細を入力します。

    • 名前: SureFire Ball (Set of 4)
    • 価格: 20.5
    • 説明: Canvas balls for practice
    • 数量: 在庫: 35
    • 数量: 出荷済: 61
  6. 「発行」をクリックします。

    セクションがリフレッシュされ、その項目が野球アクティビティ項目のリストに含まれます。

  7. リスト内のSureFireボール(セット4)アイテムをクリックし、その詳細を表示します。

    「新規アイテムの作成」ダイアログ

  8. 実行中の仮想DOMアプリケーションを表示するブラウザ・ウィンドウまたはタブを閉じます。

  9. ターミナル・ウィンドウで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を参照してください。