When To Use AJAX Callbacks Vs. When To Use Dynamic Actions

I assume you are familiar with Dynamic Actions. If not, please read this. I also assume you have a basic understanding of AJAX Callbacks, even if you’re not well-versed in the details.

Both Dynamic Actions and AJAX Callbacks allow developers to call PL/SQL from JavaScript, a highly powerful capability.

Technically, an APEX Callback can only execute PL/SQL and requires a few lines of JavaScript to initiate it. In contrast, a Dynamic Action is declarative, requires no JavaScript, and can perform numerous declarative actions—the most flexible being the Execute PL/SQL and Execute JavaScript actions.

You might wonder, given the complexity of setting up the JavaScript, why bother with AJAX Callbacks at all, especially since they are asynchronous and do not wait for the result, unlike dynamic actions.

Let’s first explore some of the advanced flexibility offered by Dynamic Actions…

Manually Triggering Dynamic Actions

Did you know that you don’t have to wait for an event to occur to trigger a Dynamic Action?

By using apex.event.trigger(pSelector, pEvent, pDataopt), you can manually call an existing Dynamic Action. I often use this to avoid code duplication when I have two identical sets of dynamic actions. For example, if I have a change event on P1_TEXT to update P1_TEXT_CHARACTER_COUNT, I want this update to happen both on Change and Key Release (i.e., as the user types in P1_TEXT). Instead of duplicating the ‘change’ code, I create an Execute JavaScript True Action on my Key Release event to call apex.event.trigger($("#P1_TEXT"), 'change', '').

Notice that pDataopt is blank in this example. In the next example, we’ll demonstrate how to use it.

Custom Events

Now that we know how to manually trigger Dynamic Actions, what if we want our Dynamic Action to be triggered only manually, without relying on events like Change or Key Release?

In this scenario, I wanted to create a True Action to call the native Alert True Action but with a dynamic message. Unfortunately, the native Alert True Action doesn’t support dynamic messages. Instead, we’ll use the apex.message.alert(this.data) function as an Execute JavaScript True Action. Think of this.data as a parameter passed from apex.event.trigger.

For example, I want to call this Dynamic Action from various places whenever I have a message to show the user. Additionally, I have another True Action to record that the user has seen an alert. This scenario suits a Dynamic Action, as it involves two actions: displaying the message and recording that the alert was shown.

Since this Dynamic Action isn’t linked to any particular event, I create it as a Custom Event, using document as the JavaScript selector and a custom event name like displayAlertAndRecord.

Finally, I call it with:

apex.event.trigger(document, 'displayAlertAndRecord', 'Did you remember to turn the gas off?');

This triggers my custom event with a parameter. Even cooler, pDataopt can be an object, array, JSON, or other data types to receive multiple parameters.

It’s worth noting that if the event were local to a region or item, I would use that as the selector instead of document.

However, there’s a caveat: pDataopt is propagated to this.data, which only exists in the browser. If I want to pass the exact alert message to my PL/SQL True Action (which saves it to the database), I face a challenge.

To address this, I might have to use a less elegant solution, like creating a single-use page item and calling:

apex.item('P1_ALERT_MESSAGE').setValue(this.data);

Then, my PL/SQL action would submit that item to the session before inserting it into the database.

This approach is less elegant because creating single-use page items is less maintainable (e.g., I have to create a new region called Control, and I may have many such items for different purposes), making pDataopt almost redundant.

Using AJAX Callbacks

This approach restores the elegance lost in the previous example, but as mentioned, setting it up involves some overhead.

The easiest way to implement this is to refer to the documentation, which provides a detailed example here…

apex.server.process( "MY_PROCESS", { x01: "test", pageItems: "#P1_DEPTNO,#P1_EMPNO" }, { success: function( data ) { // do something here console.log(data); }, error: function( jqXHR, textStatus, errorThrown ) { // handle error } } );

To get this example to work, you need to create an AJAX Callback called MY_PROCESS and perform a simple task such as:

apex_json.open_object; apex_json.write('msg_text', apex_application.g_x01); apex_json.write('msg_date', to_char(sysdate, :APP_DATE_TIME_FORMAT)); apex_json.close_object;

As seen above, JavaScript parameter values can be accessed through apex_application.g_x01.10 values, and I also have access to JavaScript arrays and all page items.

When the call is made, the results of the PL/SQL are returned to a success function. I can then dissect the data object to extract the values I’m interested in (such as the text and date in this example).

This presents an interesting capability where I can invoke an AJAX Process to store a message in PL/SQL, receive confirmation that it’s completed successfully, and then utilize the success clause to display my message.

I can encapsulate all of the above into a function like displayAlertAndRecord(pText) and call it whenever I need to display and save my message without relying on a page item.

Moreover, I can fetch multiple items from the database in one go and process them individually. This involves starting and ending in the JavaScript realm, making it quite distinct from the low-code approach.

Additionally, it’s worth noting that a list of page items (such as P1_DEPTNO and P1_EMPNO) can be submitted into the session. Some developers I know use this function primarily to push items into the session.

Contrast

Using a set of declarative Dynamic Actions to execute a series of tasks is the fastest coding method. The presence of apex.event.trigger allows you to call Dynamic Actions almost like individual functions. You might employ single-use page items to pass data between actions, especially when facing challenges with the pDataopt parameter.

In contrast, setting up AJAX callbacks can be a bit more challenging, and your PL/SQL must return data in JSON format. However, with practice, it becomes easier. They offer significant flexibility as you have full control over the logical next steps based on the returned results.