Create a form to create data records in an Oracle JET virtual DOM app
Introduction
This tutorial shows you how to use your Oracle JavaScript Extension Toolkit (Oracle JET) virtual DOM app to create a data record and submit it to a REST service.
Objectives
In this tutorial, you will learn how to write data to a REST service.
Prerequisites
- A development environment set up to create Oracle JET virtual DOM apps that includes an installation of Node.js
- Completion of the previous tutorial in this learning path, Fetch Data from a REST API in an Oracle JET Virtual DOM App
Task 1: Create Components to Manage Form Information
Create new components that will display a button used to invoke the functionality to create a new record. An ItemActionsContainer component holds the button that allows virtual DOM app users to invoke the CreateNewItemDialog component that contains the functionality to create a new record.
-
Navigate to the
JET-Virtual-DOM-app/src/components/ActivityItemdirectory, create a newCreateNewItemDialog.tsxfile, and open it in an editor. -
Add the placeholder entries that define a function name (
CreateNewItemDialog) for the new component.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; -
In the same directory, create a
ItemActionsContainer.tsxfile and open it in an editor. -
Add the placeholder entries that define a function name (
ItemActionsContainer) for the new component.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;
Task 2: Handle Opening the Dialog
Import the Oracle JET modules and declare the functions that will enable your Oracle JET virtual DOM app to successfully open a dialog.
-
At the top of the open
ItemActionsContainer.tsxfile, import the Oracle JET module for the Button component.import { h } from 'preact'; import 'ojs/ojbutton'; -
Define a
createproperty in thePropstype alias to manage opening a create dialog.import { h } from 'preact'; import 'ojs/ojbutton'; type Props = { create: () => void; }; -
In the
returnstatement, replace the existingdivelement with a newdivelement that renders anoj-buttonelement with anonojActionattribute that references thecreateproperty.const ItemActionsContainer = (props: Props) => { return ( <div> <oj-button id="createButton" onojAction={props.create}> Create </oj-button> </div>Save the
ItemActionsContainer.tsxfile. Your code should be similar toItemActionsContainer.tsx.txt -
At the top of the open
CreateNewItemDialog.tsxfile, import the Oracle JET modules for the Dialog component andMutableRefhook.import { h } from 'preact'; import 'ojs/ojdialog'; import { ojDialog } from 'ojs/ojdialog'; import { MutableRef } from 'preact/hooks'; -
Define
isOpenedandcloseDialogproperties in thePropstype alias.type Props = { isOpened: boolean; closeDialog: (ref: MutableRef<ojDialog>, type: string) => void; }; -
In the
returnstatement, replace the existingdivelement with aspanelement that wraps theoj-dialogcustom element.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> ); -
At the top of the
CreateNewItemDialog.tsxfile, import theuseRefanduseEffectPreact hooks.import { h } from 'preact'; import { useRef, useEffect } from 'preact/hooks'; import 'ojs/ojdialog'; import { ojDialog } from 'ojs/ojdialog'; -
Before the
returnstatement, declare thecreateDialogRefandcloseDialogvariables that will hold the reference that theuseRefPreact hook retrieves.const CreateNewItemDialog = (props: Props) => { const createDialogRef = useRef<ojDialog>(null); const closeDialog = () => { props.closeDialog(createDialogRef as MutableRef<ojDialog>, "create"); } return ( -
Also before the
returnstatement, use theuseEffecthook to write an expression that sets a value for theisOpenedproperty.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 (Save the
CreateNewItemDialog.tsxfile. Your code should be similar toCreateNewItemDialog-1.tsx.txt -
Navigate to the
JET-Virtual-DOM-app/src/components/ActivityItemdirectory and open theActivityItemContainer.tsxfile. -
At the top of
ActivityItemContainer.tsx, import theItemActionsContainerandCreateNewItemDialogcomponents that you just created and also import the modules for the Oracle JET Form Layout and Input Text components.import ItemActionsContainer from "./ItemActionsContainer"; import CreateNewItemDialog from "./CreateNewItemDialog"; import "ojs/ojformlayout"; import "ojs/ojinputtext"; import { ojDialog } from "ojs/ojdialog"; import { MutableRef} from "preact/hooks" -
After the
ActivityItemContainerfunction declaration, create variables that use Preact’suseStatehook and a function (openCreateDialog) to open the dialog.We also include an entry that manages the open state of an Edit dialog that we create in a later tutorial.
const ActivityItemContainer = (props: Props) => { const [isCreateOpened, setIsCreateOpened] = useState<boolean>(false); const [isEditOpened, setIsEditOpened] = useState<boolean>(false); const openCreateDialog = () => { console.log("CreateNewItemDialog called"); setIsCreateOpened(true); }; -
Before the
returnstatement, also include a function that closes an open dialog.const handleDialogClose = (ref: MutableRef<ojDialog>, type: string) => { type === "create" ? setIsCreateOpened(false) : setIsEditOpened(false); ref.current.close(); }; return ( <div id="activityItemsContainer" class=. . .> -
In the
returnstatement, include the newly-createdItemActionsContainerandCreateNewItemDialogcomponents.return ( <div id="activityItemsContainer" . . .> <div id="container"> <h3>Activity Items</h3> <ItemActionsContainer create={openCreateDialog} /> <CreateNewItemDialog isOpened={isCreateOpened} closeDialog={handleDialogClose} />Save the
ActivityItemContainer.tsxfile. Your code should be similar toActivityItemContainer-1.tsx.txt
Task 3: Handle Submitting the Dialog Input
-
Navigate to the
JET-Virtual-DOM-app/src/components/ActivityItemdirectory and open theCreateNewItemDialog.tsxfile. -
At the top of the open
CreateNewItemDialog.tsxfile, import Preact’suseStatehook.import { ojDialog } from 'ojs/ojdialog'; import { MutableRef, useRef, useEffect, useState } from "preact/hooks" -
In the
Propstype alias, define acreateNewItemproperty.type Props = { isOpened: boolean; closeDialog: (ref: MutableRef<ojDialog>, type: string) => void; createNewItem: (data: Partial<Item>, ref: MutableRef<ojDialog>) => void; }; -
Define an
Itemtype alias that includes fields for the data that you send to the REST service.type Item = { name?: string | undefined; short_desc?: string; price?: number; quantity_shipped?: number; quantity_instock?: number; }; -
Find the
oj-dialogcustom element in thereturnstatement and replace the content of<div slot="body">with anoj-form-layoutelement andoj-input-textelements for the input fields to create a new item. Also include a<div slot="footer">with anoj-buttonelement.<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> -
Before the
returnstatement, make use of theuseStatehook and include theonChangeHanderandcreateItemfunctions that the Oracle JET elements reference.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>. . .Save the
CreateNewItemDialog.tsxfile. Your code should be similar toCreateNewItemDialog-2.tsx.txt -
Navigate to the
JET-Virtual-DOM-app/src/components/ActivityItemdirectory and open theActivityItemContainer.tsxfile. -
In the
returnstatement, update theCreateNewItemDialogclass to include thecreateNewItemmethod that you defined in theCreateNewItemDialogcomponent.<CreateNewItemDialog isOpened={isCreateOpened} createNewItem={createItem} closeDialog={handleDialogClose} /> -
Before the
returnstatement, include a newcreateItemfunction that creates a new item and sends it to the backend REST service.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(); } }; -
After the
ActivityItemContainerfunction declaration, define a variable that references the URL to use to send the item to the REST service.const ActivityItemContainer = (props: Props) => { const activityItemDataProvider = props.data; const restServerURLItems = "https://apex.oracle.com/pls/apex/oraclejet/lp/activities/" + props.selectedActivity?.id + "/items/"; -
Save the
ActivityItemContainer.tsxfile. Your code should be similar toActivityItemContainer-2.tsx.txt
Task 4: Test the Code and Create a Record
-
In the terminal window, change to the
JET-Virtual-DOM-appdirectory and run the virtual DOM app.npx ojet serve - In the browser, view the dynamic changes in your virtual DOM app.
- In the virtual DOM app, click on the Baseball activity.
-
Click Create.
The Create New Item dialog opens.
-
Fill in details for a new item.
- Name:
SureFire Ball (Set of 4) - Price:
20.5 - Description:
Canvas balls for practice - Quantity: In-Stock:
35 - Quantity: Shipped:
61
- Name:
-
Click Submit.
The section refreshes and the item is part of the list of Baseball activity items.
-
Click the SureFire Ball (Set of 4) item in the list and view its details.

-
Close the browser window or tab that displays your running virtual DOM app.
- In the terminal window, press Ctrl+C, and if prompted, enter
yto exit the Oracle JET tooling batch job.
Next Step
Proceed to the next tutorial in this module.
This tutorial is part of the module CRUD Operations Using a REST Service.
- Fetch Data from the REST API in Oracle JET
- Create a Form to Create Data Records in an Oracle JET Virtual DOM App
- Update Data Records in an Oracle JET Virtual DOM App
- Delete Data Records in an Oracle JET Virtual DOM App
You can return to the virtual DOM learning path’s main page to access all the modules on building virtual DOM apps.
More Learning Resources
Explore other labs on docs.oracle.com/learn or access more free learning content on the Oracle Learning YouTube channel. Additionally, visit education.oracle.com/learning-explorer to become an Oracle Learning Explorer.
For product documentation, visit Oracle Help Center.
Create a form to create data records in an Oracle JET virtual DOM app
F70628-04