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