创建表单以在 Oracle JET 虚拟 DOM 应用程序中创建数据记录

简介

此教程演示如何使用 Oracle JavaScript Extension Toolkit (Oracle JET) 虚拟 DOM 应用程序创建数据记录并将其提交到 REST 服务。

目标

在本教程中,您将学习如何将数据写入到 REST 服务。

Prerequisites

任务 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 元素替换为新的 div 元素,该元素使用引用 create 属性的 onojAction 属性呈现 oj-button 元素。

    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 文件的顶部,导入 Dialog 组件的 Oracle JET 模块和 MutableRef 挂钩。

    import { h } from 'preact';
    import 'ojs/ojdialog';
    import { ojDialog } from 'ojs/ojdialog';
    import { MutableRef } from 'preact/hooks';
    
  5. Props 类型别名中定义 isOpenedcloseDialog 属性。

    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 文件的顶部,导入 useRefuseEffect Preact 钩子。

    import { h } from 'preact';
    import { useRef, useEffect } from 'preact/hooks';
    import 'ojs/ojdialog';
    import { ojDialog } from 'ojs/ojdialog';
    
  8. return 语句之前,声明 createDialogRefcloseDialog 变量,这些变量将保存 useRef Preact 挂钩检索到的引用。

    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 的顶部,导入刚创建的 ItemActionsContainerCreateNewItemDialog 组件,同时导入 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 语句中,包括新创建的 ItemActionsContainerCreateNewItemDialog 组件。

    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. 定义 Item 类型别名,其中包含您发送到 REST 服务的数据的字段。

    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 元素引用的 onChangeHandercreateItem 函数。

    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 语句之前,包括一个新的 createItem 函数,用于创建新项并将其发送到后端 REST 服务。

    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 Ball (Set of 4) 项并查看其详细信息。

    "Create New Item"(创建新项)对话框

  8. 关闭显示正在运行的虚拟 DOM 应用程序的浏览器窗口或选项卡。

  9. 在终端窗口中,按 Ctrl+C,如果出现提示,输入 y 以退出 Oracle JET 工具批处理作业。

后续步骤

继续本模块中的下一个教程。

本教程是 CRUD Operations Using a REST Service 模块的一部分。

您可以返回到虚拟 DOM 学习路径的主页,以访问有关构建虚拟 DOM 应用程序的所有模块。

更多学习资源

通过 docs.oracle.com/learn 浏览其他实验室,或者通过 Oracle Learning YouTube 频道访问更多免费学习内容。此外,请访问 education.oracle.com/learning-explorer 以成为 Oracle Learning Explorer。

有关产品文档,请访问 Oracle 帮助中心