Create a form to create data records in an Oracle JET web app

Introduction

This tutorial shows you how to use your Oracle JavaScript Extension Toolkit (Oracle JET) web 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

Task 1: Create a Dialog Box in the View

Use the oj-dialog custom HTML element to collect form information that you then pass to an observable.

  1. Navigate to the JET_Web_Application/src/ts/views directory and open the dashboard.html file in an editor.

  2. Find the h3 element where id="itemsListHeader". Below it, add an oj-button element and set the on-oj-action attribute to "[[showCreateDialog]]".

    <h3 id="itemsListHeader">Activity Items</h3>
    <oj-button id="createButton" on-oj-action="[[showCreateDialog]]">Create</oj-button>
    
  3. Find the oj-bind-if test="[[itemSelected()]]" element and, above it, add an oj-dialog element. Set the id attribute to "createDialog" and the style to "display:none".

    . . .
       </oj-list-view>
    </div>
    <oj-dialog id="createDialog" style="display: none" dialog-title="Create New Item" cancel-behavior="icon">
       </oj-dialog>
    <oj-bind-if test="[[itemSelected()]]">
       <div id="itemDetailsContainer" class="oj-flex-item oj-md-6 oj-sm-12">
    . . .
    
  4. Inside the oj-dialog element you created, add two child div elements with the slot="body" and slot="footer" attributes.

    <oj-dialog
      id="createDialog"
      style="display: none"
      dialog-title="Create New Item"
      cancel-behavior="icon"
    >
      <div slot="body"></div>
      <div slot="footer"></div>
    </oj-dialog>
    
  5. Add an oj-button element inside the div slot="footer" element you created, and set the on-oj-action="[[createItem]]" attribute.

    <div slot="footer">
      <oj-button id="submitBtn" on-oj-action="[[createItem]]">Submit</oj-button>
    </div>
    
  6. Inside the div slot="body" element you created, add an oj-label element and an oj-input-text element each for the Activity ID and Name values.

    
    <div slot="body">
      <oj-label class="oj-label oj-label-value" for="createActivityId">Activity ID</oj-label>
      <oj-input-text id="createActivityId" readonly value="[[activityKey]]"></oj-input-text>
      <oj-label class="oj-label" for="name">Name</oj-label>
      <oj-input-text id="name" value="{{itemName}}"></oj-input-text>
    </div>
    
    

    Note that you bind the activityKey value using square brackets, which indicates one-way binding, because the user should not edit the activity ID value. You bind the itemName value using curly brackets, which indicates two-way binding and allows the user to overwrite the value.

  7. Similarly, below the oj-input-text id="name" custom HTML element you created, add oj-input-text elements for the remaining values (price, short_desc, and so on).

    
    <div slot="body">
      <oj-label class="oj-label oj-label-value" for="createActivityId">Activity ID</oj-label>
      <oj-input-text id="createActivityId" readonly value="[[activityKey]]"></oj-input-text>
      <oj-label class="oj-label" for="name">Name</oj-label>
      <oj-input-text id="name" value="{{itemName}}"></oj-input-text>
      <oj-label class="oj-label" for="price">Price</oj-label>
      <oj-input-text id="price" value="{{price}}"></oj-input-text>
      <oj-label class="oj-label" for="short_desc">Description</oj-label>
      <oj-input-text id="short_desc" value="{{short_desc}}"></oj-input-text>
      <oj-label class="oj-label" for="quantity_instock">Quantity: In-Stock</oj-label>
      <oj-input-text id="quantity_instock" value="{{quantity_instock}}"></oj-input-text>
      <oj-label class="oj-label" for="quantity_shipped">Quantity: Shipped</oj-label>
      <oj-input-text id="quantity_shipped" value="{{quantity_shipped}}"></oj-input-text>
    </div>
    
    
  8. Save the dashboard.html file.

    Your code should look similar to this final-create-dashboard-html.txt file.

Task 2: Handle Opening the Dialog in the ViewModel

Declare the new observables and functions you referenced in the view so that your Oracle JET web app successfully initializes when you serve it.

  1. Navigate to the JET_Web_Application/src/ts/viewModels directory and open the dashboard.ts file in an editor.

  2. At the top of the dashboard.ts file, import the Oracle JET modules for the Button, Dialog, and Input Text components.

    import * as AccUtils from "../accUtils";
    . . .
    import { ojDialog } from "ojs/ojdialog";
    import "ojs/ojdialog";
    import "ojs/ojinputtext";
    import { ojButtonEventMap } from "ojs/ojbutton";
    . . .
    
  3. In the list of observables, declare and initialize observables for the fields in the create dialog.

    class DashboardViewModel {
       . . .
       //  Fields in Create dialog
       itemName: ko.Observable<string | null>;
       price: ko.Observable<number | null>;
       short_desc: ko.Observable<string | null>;
       quantity_instock: ko.Observable<number | null>;
       quantity_shipped: ko.Observable<number | null>;
       quantity: number;
       inputImageFile: string = "css/images/product_images/jet_logo_256.png";
       . . .
    
       constructor() {
          . . .
          // Initialize fields in create dialog
          this.itemName = ko.observable(null);
          this.price = ko.observable<number>(null);
          this.short_desc = ko.observable<string>(null);
          this.quantity_instock = ko.observable<number>(null);
          this.quantity_shipped = ko.observable<number>(null);
          this.quantity = 0;
          // inputImageFile has already been initialized.
       } // Closing bracket for constructor method
    
  4. Below the constructor() method, add a method named showCreateDialog for opening the dialog.

    . . .
    constructor() {
    . . .
      } // Closing bracket for constructor method
    
    // Open dialog
    public showCreateDialog(event: ojButtonEventMap["ojAction"]) {
       (document.getElementById("createDialog") as ojDialog).open();
    }
    
    
  5. Below the showCreateDialog method you created, add a method called createItem for submitting the dialog data, and add a close command.

    // Create item and close dialog
    public createItem = async (event: ojButtonEventMap["ojAction"]) => {
     (document.getElementById("createDialog") as ojDialog).close();
    }
    
    
  6. Save the dashboard.ts file.

    Your code should look similar to this create-dashboard-ts.txt file.

  7. In the terminal window, run and test your web app.

    npx ojet serve
    

    The Activity Items panel now contains a Create button. When you click it, a dialog opens.

    Create New Item dialog.

  8. Leave the terminal window and the browser window that displays your web app open.

Task 3: Handle Submitting the Dialog Input in the ViewModel

Retrieve the data from the dialog in your viewModel, send it to your REST service using the Fetch API and the HTTP POST method, and finally use the mutate method of the RESTDataProvider class to update your RESTDataProvider instance.

  1. In the open dashboard.ts file, in the createItem method above the close() call, declare variables to hold the input values from the Create New Item dialog. Also, calculate the value of quantity based on the input values for quantity_instock and quantity_shipped.

    // Create item and close dialog
    public createItem = async (event: ojButtonEventMap["ojAction"]) => {
    
       this.quantity = (Number(this.quantity_instock()) + Number(this.quantity_shipped()));
    
       const row = {
          name: this.itemName(),
          short_desc: this.short_desc(),
          price: this.price(),
          quantity_instock: this.quantity_instock(),
          quantity_shipped: this.quantity_shipped(),
          quantity: this.quantity,
          activity_id: this.activityKey,
          image: this.inputImageFile,
          };
    
      (document.getElementById("createDialog") as ojDialog).close();
    }
    
  2. Below the row variable declaration, create a request to send the data to the REST service.

    . . .
     const row = {
    . . .
       image: this.inputImageFile,
     };
    // Create and send request to REST service to add row
     const request = new Request(this.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();
     . . .
    
  3. Below the addedRow variable, create an add mutate event and call the RESTDataProvider class’s mutate method to notify your RESTDataProvider instance that a new row has been added. You also call the RESTDataProvider class’s refresh() method to refresh the display.

       . . .
       const addedRow = await response.json();
       // Create add mutate event and call mutate method
       // to notify dataprovider that a row has been
       // added
       const addedRowKey = addedRow[this.keyAttributes];
       const addedRowMetaData = { key: addedRowKey };
       this.itemsDataProvider.mutate({
       add: {
          data: [addedRow],
          keys: new Set([addedRowKey]),
          metadata: [addedRowMetaData],
       },
       });
       this.itemsDataProvider.refresh();
       // Close dialog
       (document.getElementById("createDialog") as ojDialog).close();
    
    }
    
  4. Save the dashboard.ts file.

    Your code should look similar to this final-create-dashboard-ts.txt file.

Task 4: Test the Code and Create a Record

  1. In the browser, view the dynamic changes in your web app.

  2. In the web app, click on the Baseball activity.

  3. Click Create.

    The Create New Item dialog opens.

  4. 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
  5. Click Submit.

    The section refreshes and the item is part of the list of Baseball activity items.

  6. Click the SureFire Ball (Set of 4) item in the list and view its details.

    Create New Item dialog

  7. Close the browser window or tab that displays your running web app.

  8. In the terminal window, press Ctrl+C, and if prompted, enter y to exit the Oracle JET tooling batch job.

Next Step

To proceed to the next tutorial in this learning path, click here.

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.