Show an animated “Please wait” indicator after page submit

My application normally responds to button clicks with sub-second performance, but there were a few operations where users can initiate quite long-running transactions (e.g. up to 15 seconds long in one case where it was hitting an eBus interface thousands of times).

When the user clicks the button, I want the page to show a “Please Wait” message with an animated running indicator (I won’t call it a “progress bar” even though it looks like one, because it doesn’t really show progress, it just rotates forever) until the page request returns.

pleasewait

To do this I added the following to my application, based largely on this helpful article.

1. Add an HTML region on Page 0 (so it gets rendered on every page) at Before Footer, with:

<div id="runningindicator">
Processing, please wait...
<div id="runningindicator-img"></div>
</div>

2. Add the following to the global CSS file for my application:

div#runningindicator {
  display: none;
  background-color: #FFF;
  padding: 30px;
  border: 1px solid;
  border-color: #CCC;
  box-shadow: 2px 2px 2px #AAA;
  border-radius: 4px;
  position: absolute;
  top: 100px;
  left: 50%;
  margin-left: -110px;  /* the half of the width */
}
div#runningindicator-img {
  background-image: url(/i/processing3.gif);
  background-repeat: no-repeat;
  width: 220px;  /* the exact width of the image */
  height: 19px;  /* the exact height of the image */
}

3. Add the following to the global javascript file for my application:

function run_long_request (request, warnmsg) {
  if (!warnmsg || confirm(warnmsg)) {
    // disable all buttons on the page
    var btns = $("a[role='button']");
    $x_disableItem(btns, true);
    $("div#runningindicator").show();
    apex.submit(request);
  }
}

4. Change the button:

Action = Redirect to URL
URL Target =

javascript:run_long_request('APPROVE',
  'Are you sure you wish to approve this transaction?');

When clicked, the button runs my javascript function which first prompts the user to confirm, and if they do, it disables all the buttons on the page, shows the running indicator, and submits the request (which might be the name of the button, for example).

If I omit the second parameter, the function skips the confirm popup and submits straight away.

Known Issue: the animated gif doesn’t seem to animate in IE8. So far I haven’t worked out how to solve this, except to burn IE8 with fire and extreme prejudice. I’ve tried using setTimeout to delay showing the div but it stubbornly stays frozen.

EDIT: thanks to Peter Raganitsch who alerted me to a simpler option, that doesn’t need the region or the CSS, and animates in IE8:

function run_long_request (request, warnmsg) {
  if (!warnmsg || confirm(warnmsg)) {
    apex.submit({request:request,showWait:true});
  }
}

Mind you, building this sort of thing from scratch was a useful exercise to learn the CSS and javascript tricks necessary. And another thing re-learned: there’s almost always a simpler way.

Split CLOB into lines
AUSOUG 2014 Perth Conference

Comments

  1. Hi Jeff,

    I appreciate your efforts to sharing useful code globally.
    I have one doubt .how to display show-wait on ajax call which would not need to submit page. Any suggestion?

  2. Hi Amol,

    You can show the spinner in javascript (e.g. as one of your dynamic action steps) using apex.util.showSpinner.

    To show the spinner:

    lSpinner$ = apex.util.showSpinner( $( "#container_id" ) );

    To remove the spinner:

    lSpinner$.remove();

    If I were to put the above code in a dynamic action, I’d put the following declaration in the page’s Function and Global Variable Declaration property:

    var lSpinner$;

    Reference:

    https://docs.oracle.com/database/apex-5.1/AEAPI/apex-util-namespace.htm#AEAPI30161

    I hope this helps.

  3. That’s fine Jeff. But apex.util.showSpinner doesn’t show when you have a PL/SQL process in the middle of a DA until the end of the DA.

    Ie; Step 1 – apex.util.showSpinner
    Step 2 – Long-running PL/SQL
    Step 3 – Remove spinner

    The spinner won’t show until AFTER step 2, which ofc then gets immediately removed as that’s the next instruction. I want it to show at step 1, before step 2 starts.

  4. Hi Jeff,

    Thanks for the code.. But I would like to know how can we replicate the same functionality on form load? My Apex application form is being invoked by some other application(non apex). Please guide.

    • Hi Nikita, that’s a good question. If your page takes a long time to load, your code won’t run until it’s fully loaded; so to show the spinner I think you may need to move the bulk of the workload to a separate ajax call (using a Dynamic Action that runs on Page Load).

  5. Hi Jeff,

    Actually, there is a non apex application that is writing data into my oracle database and invoking my apex application to see the newly written data. Now the problem is, it is taking about 6-10 seconds for the non apex app to write data into my database. So when it invokes my apex app, the page report shows no data found error and after a few seconds, when I reload the page, it shows the data successfully. So this is due to latency in writing data into my apex app. Hence, I want to show a spinner for 6-10 seconds when the page is invoked so that this time will be consumed to write data into DB and after 6-10 seconds, the page must show the data. I am using Apex 4.2. Please help

  6. Hi Jeff,

    Thanks alot for your help!!

    I tried to auto refresh after 5 seconds interval.. But I need to do this refresh activity only once because anyhow, my data gets loaded in that amount of time.

    Also need your help to understand, where(event) should I write the SQL query to check my DB?

    • Hi Nikita,

      To refresh a report, you add a “Refresh” dynamic action to your page. That’s all you need.

      The tricky part is delaying it for a set interval. To do this you need to run some custom javascript:


      setTimeout(function() {apex.region("myRegionId".refresh()}, 6000);

      In the call above, 6000 means “wait for 6 seconds”. Whatever appears within the function will be executed after that time.

      You will need to set a static ID on the report region, e.g. myRegionId.

  7. Hi Jeff,

    Thanks for the help.. It works fine now.. But there is an additional requirement in the code, where in the page should run the dynamic action to show the progress bar only 3 times. After which it should move to the error page saying record not loaded.. how do I achieve that

  8. is there any way to remove spinner dynamically instead of putting seconds?
    setTimeout(function() {apex.region(“myRegionId”.refresh()}, 6000);

    • Jeffrey Kemp
      30 May 2022 - 2:20 pm

      Hi Fahad,

      Yes, if you create a Dynamic Action that fires when the event you specify occurs.

Leave a Reply

Your email address will not be published / Required fields are marked *