When to AJAX Callback vrs. When to Dynamic Action

I am going to assume you know what Dynamic actions are, if not read this. I am also going to assume you are aware of the basics of what an AJAX Callback is, without knowing the ins and outs.

Both Dynamic Actions and AJAX Callbacks share similarities in that they both allow the developer to call PL/SQL from JavaScript; and that is a very powerful tool.

Strictly speaking, an APEX Callback can only be PL/SQL but needs a handful of lines of JavaScript to call it. Whilst a Dynamic Action is declarative, requires no JavaScript, and can perform dozens of declarative actions – the most flexible being the Execute PL/SQL and Execute JavaScript actions.

You might be thinking, given the hassle of setting up the JavaScript, why even should I bother with AJAX Callbacks? They are not even synchronous like dynamic actions – i.e. AJAX Callbacks do not wait for the result.

First, let us look a bit at some of the advanced flexibility of Dynamic Actions…

Calling Dynamic Actions Manually

Did you know? you do not have to actually wait for the event to occur to call a Dynamic Action?

Simply calling apex.event.trigger(pSelector, pEvent, pDataopt) will it call an existing Dynamic Action. I typically use this when I have two identical sets of dynamic actions and I do not want code duplication. For example, I have a change event on P1_TEXT to set a P1_TEXT_CHARACTER_COUNT item. I not only want to set it on Change, but also on Key Release (i.e. as the user is typing within P1_TEXT). Instead of duplicating the ‘change’ code, I create a Execute JavaScript True Action on my Key Release to call apex.event.trigger($(“#P1_TEXT”), ‘change’, ‘’);

Notice the pDataopt is blank in the above. In the next example, we will put it to some use.

Custom Events

So now we know how to call Dynamic Actions manually, what if our Dynamic Action is only triggered manually? I.e. not even by a Change or Key Release Event.

In this scenario, I wanted to create a True Action to call the native Alert true action; but I actually want to set my own message dynamically. Unfortunately the native Alert true action doesn’t support a dynamic message, so instead we’ll use the apex.message.alert(this.data) function as a Execute JavaScript True Action. Think of this.data as a parameter passed from apex.event.trigger.

The scenario is I want to call this Dynamic Action from various places, whenever I have a message to show the user, I also have another True action to record that the user has seen an alert. This would suit a Dynamic Action, as it is a set of two actions to perform: the first to display the message, the second is to record that an alert has been shown.

Since this Dynamic Action is linked to no particular event, I create it as a Custom Event, with a JavaScript of document and my own custom name of displayAlertAndRecord.

Finally I call it with apex.event.trigger( document, ‘displayAlertAndRecord’, ‘Did you remember to turn the gas off?’);

Bingo, my custom event is called with a parameter. What is cooler is that pDataopt can be an object, an array, a JSON or whole bunch of stuff to receive multiple parameters.

It is worth mentioning, if the event were local to a region or item, I would use that as the selector rather than document.

There is a caveat though… notice that pDataopt is propagated through to this.data, which only exists in the browser, so if I wanted to pass the exact alert message that was displayed through to my PL/SQL true action (which saves it to the database) then I am a bit struck.

Instead I’ll have to create something less elegant… for example creating a single-use page item and calling apex.item(‘P1_ALERT_MESSAGE’).setValue(this.data);. Furthermore, I would have get my PL/SQL action submit that item in to session before that inserted it in to the database.

It is less elegant as creating a single-use page item is less maintainable (i.e. I have to create a new region called something like Control and I may have many of these items doing different things) and using pDataopt is now almost pointless. Cue…

AJAX Callbacks

This provides the elegance lost in the above example… however as described already, there is a bit of an overhead setting it up.

Easiest way is actually look at the documentation here which provide this example…

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 I use need to create an AJAX Callback called MY_PROCESS and do something simple like

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 you can see from the above, JavaScript parameter values can get accessed by apex_application.g_x01.10 values and I have also have access to JavaScript arrays and all the page items.

When it is called, the results of the PL/SQL are returned to a success function. I can pick apart the data object to fish out the values I’m interested in (in this example the text and date).

This is interesting, as I can call an AJAX Process to store the message in PL/SQL, give me the OK that it has been completed, and then I can use the success clause to show my message.

I can wrap all the above up in to a FUNCTION displayAlertAndRecord(pText) and call this anytime to display and save my message without burning up a page item.

I can also return several items from the database in one shot and process them individually. In order to do this, I start and finish in the JavaScript world, so it is quite distant from the low-code approach.

In addition, notice a list of pageItems (P1_DEPTNO and P1_EMPNO) can be submitted in to session. I know of developers that typically use this function just to push items in to session.

Comparison

A set of declarative Dynamic Actions that perform a series of tasks is the quickest way of coding. The presence of apex.event.trigger means you can call Dynamic Actions as almost individual functions. You may use single-use page items to hand-off between actions where you may get unstuck using the pDataopt parameter.

AJAX callbacks on the other hand get be a little more difficult to set up and your PL/SQL needs to return in a JSON format, although with practice, it is easier. With a bit of work they can offer a tonne of flexibility as you have complete control what to logically do next based on the results returned.

Matt Mulvaney Contributor
Senior Oracle APEX Development Consultant , Explorer UK Ltd

Matt is an experienced APEX solution designer having designed numerous complex systems using a broad range of Oracle Technologies. Building on his previous experience of Oracle Forms & PL/SQL, he is entirely focused on providing functionally rich APEX solutions. Matt promotes APEX as a software platform and openly shares best practises, techniques & approaches. Matt has a passion for excellence and enjoys producing high quality software solutions which provide a real business benefit.

follow me