How implement load and wait spinners in Oracle APEX

How implement load and wait spinners in Oracle APEX

Who hasn't dealt with a pesky user who generates those hard-to-debug errors, only to discover in the end that the person simply clicked a button multiple times and executed the process multiple times?

Today, I'm going to teach you a tip that will solve this once and for all, and you can apply it in multiple contexts. Check this out

The difference between load and wait spinner's

The spinners that users can interact with the page are called "load spinners." They are often used to indicate that the server is loading something. You commonly see them in APEX when loading a Report region. It looks like this 👇🏽

Spinners that don't allow user interaction with the page are called "wait spinners." They block interactions with the page and are typically seen when executing a process. APEX provides them natively through the page processing tab after a submission. Check it out 👇🏽

Calling a wait spinner from JavaScript

There are multiple contexts to use this spinner, in my demo I will use it thinking that my form is really big and there will be multiple calculations / set values in my form inputs.

To accomplish this, we can simply navigate to the page attributes and, within the JavaScript group properties, open the 'Execute when Page Loads' property editor to insert some code:

let waitSpinner = apex.widget.waitPopup() //call the wait spinner

setTimeout(() => {
    waitSpinner.remove(); //remove the wait spinner after 3 seconds
} ,3000)

As I said earlier, we can invoke this function at the end of an operation. This is particularly useful when dealing with extensive processes that may consume several seconds.

In my demonstration, I will be inserting a file into the database. When the user clicks the 'Finish' button, the spinner will be invoked to prevent the user from clicking multiple times or canceling the dialog.

To achieve this, the 'FINISH' button is bound to a dynamic action that triggers the wait spinner:

PS: Is the same code that I provided earlier

This way, the spinner is invoked while the file is being inserted by the page process.

Alternatively, for this context, you can create a custom Dynamic Action to do it:

  • Create a custom Dynamic Action:

    • For name: nativeWaitPopUp

    • For Custom Event: waitSpinner

    • For Selection Type: Select Javascript Expression

    • For JavaScript Expression: document

  • Define a single true action that will submit the page.

  • In the Settings property group, switch ‘Show Processing’ to ON

    • In my demo, the ‘FINISH’ button was submitting the page

    • But for only one process to run I changed the behavior of my FINISH button to 'Defined by Dynamic Action'

    • This way, we can assign a ‘FINISH’ request in the submit page custom Dynamic Action

Now, we simply trigger the custom event when the 'FINISH' button is pressed:

apex.event.trigger(document,'waitSpinner',{});

Calling load spinner from JavaScript

For this demonstration, I have an employee report that includes a column called "curriculum." This column is a hyperlink column that links to another page, which in turn loads and displays the PDF curriculum of the employee.

PS: This implementation will be addressed by me in another article.

Consider a situation where the file may be lengthy or the query/API is slow in returning a response. In this scenario, the user might encounter an empty screen. Hence, we will implement a spinner call to indicate that data is being loaded from the server.

In my implementation, I invoke the following function. Let's take a look at it:

  • I've declared the variable loadSpinner below, and then I invoked the apex.util.delayLinger.start method.

  • This method takes another function as an argument. Inside that function, I assign the spinner to the variable we created earlier.

  • Consequently, when the process is completed, I can simply call my variable using the .remove() method to hide the spinner.

For my demonstration, I introduced a delay to call the function responsible for constructing my PDF viewer container.

An example of load spinner:


var loadSpinner 
apex.util.delayLinger.start( "main", function() {
    loadSpinner = apex.util.showSpinner( $( "#yourRegionStaticID" ) ); 

} );

function your_function(){
    //do something
    loadSpinner.remove(); //the spinner will be removed
}

Every time you make a lengthy AJAX callback, you can also trigger the load spinner. This way, users will be aware that the server is processing something and will wait until it's completed.

Conclusion

You've gained insights into the distinction between a wait spinner (for non-interaction) and a load spinner (for user interaction).

Additionally, you've acquired knowledge on how to invoke them using JavaScript via the apex.widget.waitPopup() and apex.util.showSpinner() functions.

If you found this article helpful, please consider liking and sharing it with others.