Have a process that takes several seconds (10-60) to execute?  Is it processed as a series of steps?  We can show the processing message, but often the user may get impatient at seeing an indeterminate progress bar.   The user, after a while, will want to be informed that something is actually going on and not just stuck in an endless loop.  In this article I will share a technique to provide feedback to the user while doing some processing.

This example is based upon APEX 4.2.5.  View the demo.

Basically, this functionality will be driven by several Dynamic Actions which:

  1. Create and show the modal progress bar.
  2. Start a timer to repeatably read the status table application items session state values.
  3. Run the process which includes autonomous updates to the application items session state. to our status table.
  4. Close the progress bar and stop the timer when the process is finished.

The example uses the APEX timer plugin. Download and install the timer Dynamic Action Plugin from http://www.oracle.com/technetwork/developer-tools/apex/application-express/apex-plug-ins-182042.html#dynamic

In the example I use a table to update and read the process status.  The table consists of a single row and is updated by calling an autonomous transaction procedure. One could also write and read the status from the tables used in the Logger utility.  

CREATE TABLE process_status ( status_message VARCHAR2(1000), status_percent NUMBER ) / INSERT INTO process_status ( status_message, status_percent) VALUES ( 'xxx', 0 ) /

create or replace procedure "UPDATE_PROCESS_STATUS" (p_status_message VARCHAR2, p_status_percent NUMBER) is PRAGMA AUTONOMOUS_TRANSACTION; begin UPDATE process_status SET status_message = p_status_message, status_percent = p_status_percent; COMMIT; end;‚Äč

The progress bar that is shown and used is the jQuery UI progressbar.  APEX does not load this progressbar widget by default but the code for it is included in the APEX installation.  It can be loaded by referencing the JavaScript and CSS files in the page definition.

    // Page Definition JavaScript File URLs<br />
    /i/libraries/jquery-ui/1.8.22/ui/minified/jquery.ui.progressbar.min.js<br />
    // Page Definition CSS File URLs<br />
    /i/libraries/jquery-ui/1.8.22/themes/base/minified/jquery.ui.progressbar.min.css

In the page definition footer text is the HTML code for the popup window and the progress bar.

<div id="progresspopup" class="popup">
  <div id="progressbar"></div>
</div>

The page has an item button (P104_START_PROCESS) with the button action set to a dynamic action.

The page has two page items (P104_PROCESS_MESSAGE, P104_STATUS_PERCENT) that will be used to store the process message and percentage completed.

The first dynamic action is run on the click of the button with three true actions: Execute JavaScript Code, Timer [Plug-in], and Execute PL/SQL Code.

The Execute JavaScript Code true action is used to create and show a modal dialog box and progress bar.

$("#progresspopup").dialog({ 
  modal: true, 
  closeOnEscape: false, 
  height: 75, 
  title: "Initializing Progressbar", 
  resizable: false, 
  hide: 1500});

$(".ui-dialog-titlebar-close").hide();

$("#progressbar").progressbar();

 

The Timer [Plug-in] true action is used to add a timer that expires every 500 milliseconds.

The Execute PL/SQL Code true action is use to run the processing code.  Between each step of processing the UPDATE_PROCESS_STATUS procedure is called to update the process_status table.  the application items session state value is updated by executing the APEX_UTIL.SET_SESSION_STATE procedure.
*** The "Wait For Result" checkbox needs to be unchecked ***

The second dynamic action is run every time the timer has expired and has two true actions: Set Value, Execute JavaScript Code

The Set Value true action is used to read the values from session state the process_status table and save them to our page items.

Then the Execute JavaScript Code true action is used to update the modal dialog title and the progressbar value.

$("#progresspopup").dialog("option","title",$v("P104_PROCESS_MESSAGE")); 
$("#progressbar").progressbar( "value",parseInt($v("P104_STATUS_PERCENT")));

The third dynamic action is also set to run every time the time expires but has a condition to only execute the true actions when the status percent item value is 100.  It has two true actions: Execute JavaScript Code, Timer [Plug-in].

The Execute JavaScript Code true action will close our modal dialog box and progressbar.

$("#progresspopup").dialog("close");
$.delay(2000);
$("#progressbar").progressbar("destroy");
$("#popup").dialog("destroy");

The Timer [Plug-in] true action is used to remove the timer that was created in the first dynamic action.

By the end all our page Dynamic Actions will look like: