Update 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 update an existing data record and submit it to a REST service.

Objectives

In this tutorial, you will learn how to update an existing data record and submit it 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, which 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 oj-button id="createButton" element and add a second oj-button element below it. Set the on-oj-action attribute to "[[showEditDialog]]" and the disabled attribute to "[[!itemSelected()]]".

    . . .
    <h3 id="itemsListHeader">Activity Items</h3>
     <oj-button id="createButton" on-oj-action="[[showCreateDialog]]">Create</oj-button>
    <!-- If itemSelected is set to false, disabled is true, and vice versa. -->
    <oj-button id="updateButton" disabled="[[!itemSelected()]]" on-oj-action="[[showEditDialog]]">Update
      </oj-button>
    <oj-list-view id="itemsList" class="item-display" data="[[itemsDataProvider]]"
    . . .
    
  3. Find the oj-bind-if test="[[itemSelected()]]" tag and add an oj-dialog element inside it. Set the id attribute to "editDialog" and the class attribute to no-display.

    . . .
    <oj-bind-if test="[[itemSelected()]]">
       <oj-dialog id="editDialog" class="no-display" dialog-title="Update Item Details" cancel-behavior="icon">
          </oj-dialog>
    <div id="itemDetailsContainer" class="oj-flex-item oj-md-6 oj-sm-12">
       <h3>Item Details</h3>
    . . .
    
  4. Inside the oj-dialog element you created, add two div tags with the slot="body" and slot="footer" attributes.

    <oj-dialog id="editDialog" class="no-display" dialog-title="Update Item Details" 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="[[updateItemSubmit]]" attribute.

    <div slot="footer">
               <oj-button id="submitBtn" on-oj-action="[[updateItemSubmit]]">Submit
               </oj-button>
             </div>
    
  6. Inside the div slot="body" tag you created, add an oj-label-value, an oj-label element, and an oj-input-text element for the inputItemID value.

    <div slot="body">
      <oj-label-value label-edge="inside">
       <oj-label for="chatWindow" slot="label">Item ID</oj-label>
       <div slot="value" class="slot-line">
         <oj-bind-text id="chatWindow" value="[[inputItemID]]" class="text-width"></oj-bind-text>
       </div>
     </oj-label-value>
    </div>
    
  7. Below the oj-label-value element, add oj-input-text elements for the Name, Price, and Description values.

    
    <div slot="body">
       . . .
       </oj-label-value>
       <oj-label class="oj-label oj-label-value" for="createNewName">Name</oj-label>
       <oj-input-text id="createNewName" value='{{inputItemName}}'></oj-input-text>
       <oj-label class="oj-label oj-label-value" for="createNewPrice">Price</oj-label>
       <oj-input-text id="createNewPrice" value="{{inputPrice}}"></oj-input-text>
       <oj-label class="oj-label oj-label-value" for="createNewDesc">Description</oj-label>
       <oj-input-text id="createNewDesc" value="{{inputShortDesc}}"></oj-input-text>
    </div>
    
    

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

  8. Verify that the List View component with id="itemsList" specifies selectedItemChanged as a value for the on-first-selected-item-changed attribute.

  9. Save the dashboard.html file.

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

  10. Navigate to the JET_Web_Application/src/css directory and open the app.css file. Add the following style definitions to the end of the file.

    . . .
    .no-display {
       display: none;
    }
    
    .slot-line {
       line-height: 2.4em;
    }
    
    .text-width {
       width: 100%;
       min-width: 100%;
    }
    

    Your code should look similar to this final-css.txt file.

Task 2: Handle Opening the Dialog in the ViewModel

Declare the new observables and methods 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, verify that the Oracle JET modules for the Dialog component and the Input Text component are imported.

    import * as AccUtils from "../accUtils";
    . . .
    import { ojDialog } from "ojs/ojdialog";
    import "ojs/ojdialog";
    import "ojs/ojinputtext";
    . . .
    
  3. Within the DashboardViewModel class, below your previous code for creating a new Activity Item, create a method called showEditDialog to open the dialog and retrieve the values of the fields that you want to update.

    . . .
    public createItem = async (event: ojButtonEventMap["ojAction"]) => {
    . . .
     } // end createItem
    
    public showEditDialog = (event: ojButtonEventMap["ojAction"]) => {
    
          this.inputItemName(this.itemData().name);
          this.inputPrice(this.itemData().price);
          this.inputShortDesc(this.itemData().short_desc);
    
       (document.getElementById("editDialog") as ojDialog).open();
     }
    
  4. Below the showEditDialog method, create a method called updateItemSubmit to submit the dialog data, and add a close command.

    public showEditDialog = (event: ojButtonEventMap["ojAction"]) => {
    
          this.inputItemName(this.itemData().name);
          this.inputPrice(this.itemData().price);
          this.inputShortDesc(this.itemData().short_desc);
    
       (document.getElementById("editDialog") as ojDialog).open();
     }
    
    public updateItemSubmit = async (event: ojButtonEventMap["ojAction"]) => {
       (document.getElementById("editDialog") as ojDialog).close();
    }
    
  5. Save the dashboard.ts file. Your code should look similar to this update-dashboard-ts.txt file.

Task 3: Handle Submitting the Dialog Input in the ViewModel

Create objects to hold the data that you fetch from the dialog in your view, and send it to the REST service using the Fetch API and the HTTP PUT method. Finally, use the mutate method of the RESTDataProvider class on your RESTDataProvider instance.

  1. In the open dashboard.ts file, in the DashboardViewModel class, declare types for and initialize the following variables that you will use in the method that submits data.

    class DashboardViewModel {
       . . .
       // Fields in update dialog
       inputItemID: ko.Observable<number | null>;
       inputItemName: ko.Observable<string | null>;
       inputPrice: ko.Observable<number | null>;
       inputShortDesc: ko.Observable<string | null>;
    
       //  Fields for delete button and update dialog, among others
       selectedRow = ko.observable<number>();
    
       . . .
    
       constructor() {
       . . .
          // Initialize fields in update dialog
          this.inputItemID = ko.observable(null);
          this.inputItemName = ko.observable(null);
          this.inputPrice = ko.observable(null);
          this.inputShortDesc = ko.observable(null);
    
       } // End constructor
    
  2. In the updateItemSubmit method above the close() call, declare a variable, row, to hold the input values from the Update Item Details dialog. Also include an if statement to check that data has been selected.

    public updateItemSubmit = async (event: ojButtonEventMap["ojAction"]) => {
        const currentRow = this.selectedRow;
             if (currentRow != null) {
                const row = {
                   itemId: this.itemData().id,
                   name: this.inputItemName(),
                   price: this.inputPrice(),
                   short_desc: this.inputShortDesc()
                };
       }; // End if statement
     (document.getElementById("editDialog") as ojDialog).close();
    }
    
  3. Above the close() call, create a request to send the data to the REST service.

    public updateItemSubmit = async (event: ojButtonEventMap["ojAction"]) => {
    
     const currentRow = this.selectedRow;
    
     if (currentRow != null) {
    
       const row = {
       	. . .
          short_desc: this.inputShortDesc()
       };
    
    // Create and send request to update row on rest service
       const request = new Request(
    
         `${this.restServerURLItems}${this.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();
     } // End if statement
     (document.getElementById("editDialog") as ojDialog).close();
    
    }  // update-item-end
    
  4. Below the request to send data to the REST service, create an update mutate and call the mutate() method to notify your RESTDataProvider instance that data has been updated. Also call the refresh() method to refresh the data that displays in the browser.

    public updateItemSubmit = async (event: ojButtonEventMap["ojAction"]) => {
    
    const currentRow = this.selectedRow;
    
       if (currentRow != null) {
          . . .
    
       };
    
       const request = new Request(
    
       `${this.restServerURLItems}${this.itemData().id}`,
          {
             . . .
          }
          );
    
    . . .
       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 = this.itemData().id;
       const updatedRowMetaData = { key: updatedRowKey };
       this.itemsDataProvider.mutate({
       update: {
          data: [updatedRow],
          keys: new Set([updatedRowKey]),
          metadata: [updatedRowMetaData],
       },
       });
       this.itemsDataProvider.refresh();
    
       } // End if statement
       (document.getElementById("editDialog") as ojDialog).close();
    }  // update-item-end
    
  5. Save the dashboard.ts file.

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

Task 4: Test the Code and Update a Record

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

  2. In the web app, click the Baseball activity, and then click the SureFire Ball (Set of 4) item.

  3. Click the Update button.

    The Update Item Details dialog pops up.

  4. Change the price from 20.5 to 21 and click Submit.

    The section refreshes and the price of the item has been updated.

    Update Item Details

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

  6. 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.