更新 Oracle JET 虚拟 DOM 应用程序中的数据记录

简介

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

目标

在本教程中,您将学习如何更新现有数据记录并将其提交到 REST 服务。

Prerequisites

任务 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. 在文件顶部,导入 useStateuseEffect 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 Dialog 组件以及 useRefuseEffectMutableRefuseState 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 自定义元素引用的子自定义元素中添加属性值的方法。例如,当 oj-input-text 组件通过其 onvalueChanged 属性检测更改时,将调用 onChangeHandler 方法。

     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 函数之前,定义一个 Item 类型别名,其中包含您更新并发送到 REST 服务的数据的字段。

    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 语句中,使用 itemSelectededit 属性值更新 ItemActionsContainer 元素。在 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 函数以打开编辑对话框,添加 editItem 函数以将更新的活动项发送到 REST 服务。

     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. 单击更新按钮。

    此时将弹出 "Update Item Details" 对话框。

  5. 将价格从 20.5 更改为 21,然后单击提交

    区段将刷新,并且货品的价格已更新。

    更新项详细信息

  6. 关闭显示正在运行的虚拟 DOM 应用程序的浏览器窗口或选项卡。
  7. 在终端窗口中,按 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 帮助中心