Editable Table in Oracle VBCS with Asynchronous Edit Handling


UPDATE NOTE (22/11/2023): As of the latest Release 23.10, VB has provided an easier way to achieve this functionality.

Locate tableBeforeRowEdit under eventListners in the JSON code and add "asyncBehavior": "enabled" for both events. The final code should look like this:

  "eventListeners": {
    "tableBeforeRowEdit": {
      "asyncBehavior": "enabled",
      "chains": [{ ... }]
    },
    "tableBeforeRowEditEnd": {
      "asyncBehavior": "enabled",
      "chains": [{ ... }]
    }

Follow this VB Cookbook: vbcookbook.oracle.com/?page=shell&shell..

The rest of the blog defines the problem and provides solutions which were helpful before the 23.10 release


One of the common issues with an editable table was that when the number of columns was more we see behavior where "previous row data shows up in the current row being edited for a fraction of a second". We can find many discussions around this on Customer Connect.

Let us take an example of an editable table implemented in VBCS. Assume there are few rows in the table. currentRowBuffer is the variable storing the row data being edited and we are editing the 1st Row.

Now, as soon as we double click on the second row to take that into edit mode these are the steps that happen,

  1. 1st Row comes out of edit mode

  2. 2nd Row goes into edit mode

Since these two are occurring in parallel there is a split second where the second row's edit mode will show the data of the first row.

Why?

Because in VBCS Action chains bound to events are Asynchronous. So there can be a delay between the row going into edit mode (showing the data of currentRowBuffer) and the action chain assigning the new data (2nd Row) to currentRowBuffer.

How to resolve this?

We have a new feature in JET to our rescue. ojBeforeRowEdit now has a method called "accept". Pass a Promise to the "accept" method of the ojBeforeRowEdit detail. The Table will display a loading indicator while waiting for the Promise to resolve or be rejected. until this is not resolved the row will not go into edit mode.

Great, JET Cookbook already has this implemented which can be referred to here. But how do we use that in VBCS?

Simple,

  1. Implement the editable table the normal way.

  2. Then replace the ojBeforeRowEdit edit event to call a JS function that will add the accept promise.

     <oj-table edit-mode="rowEdit" 
     on-oj-before-row-edit="[[ function (event) { $page.functions.lineTableBeforeRowEdit(event) } ]]" ....>
     ......
     </oj-table>
    
  3. In that JS Call the event that was previously bound to ojBeforeRowEdit.

     lineTableBeforeRowEdit(event) {
           let detail = event.detail;
           event.detail.accept(new Promise(function (resolve) {
             this.rowBeforeEditPromise = resolve;
             this.eventHelper.fireCustomEvent("tableBeforeRowEdit", {
               "detail": event.detail
             });
             // reject(); when required
           }.bind(this)));
         }
    
  4. The action chain should do its work (assign the currentRowBuffer and any other) and then finally resolve the Promise by calling a second JS so that row goes into edit mode.

     resolveRowBeforeEditPromise() {
           if (this.rowBeforeEditPromise) {
             this.rowBeforeEditPromise();
             delete this.rowBeforeEditPromise;
           }
         }
    

Below is a video describing the same. Ignore the first 10 minutes if you know how to implement the Editable Table the normal way.

Also, the sample app can be found in my GIT.