When I want to invoke a server side process from a dynamic action (DA), I have two choices:
Create a DA Action of type "Execute Server-side Code"
Create a DA Action of type "Execute Javascript Code" and then write the javascript to invoke an Ajax Callback process.
Option 1 seems like a lot less work. It has a drawback, though: the only way to pass data from the browser to the "Execute Server-side Code" action is by passing page items using the "Items to Submit" attribute. (OK, there is a corresponding drawback: the only way to get data back is via the "Items to Return" attribute). That often requires you to create hidden items (that are not session state protected and that do not warn on unsaved changes). Then you have to process subsequent actions based upon those items.
Option 2 allows you to pass data into the apex_application.g_f0x PL/SQL variables; you don't need to create those extra hidden items. But option 2 requires you to remember how to call the APEX Ajax Callback process via Javascript--and to write it and test it.
TLDR
APEX really should have a native DA type "Invoke Ajax Callback" that allows you to declaratively call the Ajax Callback process. Please up-vote the APEX idea FR-3883 that describes this. In the meantime, you can use the plug-in Marwa and I created. (Update: FR-3883 was closed because the APEX team plans to re-work the way Ajax calls happen within the APEX engine. Look for a significant new feature in an upcoming release. Until then you can use our plug-in.)
The link to the plug-in is https://github.com/ainielse/invoke_ajax_callback
Also check out APEX Instant Tips episode #147.
The Challenge
You can see the results in action here:
https://apex.oracle.com/pls/apex/r/mchouchene/ait-147/employees
We have a report column link that passes the EMPNO to a DA. The DA invokes an Ajax Callback process, passing both the EMPNO and the value of the P4_RAISE_PERCENT item. The javascript required to do this is
var da = this;
var processName = da.action.attribute01;
var itemsToSubmit = da.action.attribute02;
apex.server.process(
processName, {
x01: this.data.empno,
pageItems: itemsToSubmit
}, {
success: function(data) {
console.log('success', data.message);
apex.message.showPageSuccess(data.message);
apex.da.resume(da.resumeCallback, false);
},
error: function(error) {
apex.message.showErrors(error.responseText)
}
}
);
}
Sure, this isn't hard, but it's also not super easy. And if you want to do something other than show a message you have to remember how to do it (or, in my case, look up how to do it each time). You may want to take different kinds of actions: raise a custom event, call a Javascript function, etc. Each of these requires you to recall exactly how to do it.
The Plug-in
To make our own lives easier, we created a plug-in that provides a declarative way to invoke the Ajax Callback process. Because we are oh so creative, we named the plug-in "Invoke Ajax Callback."
The plug-in contains significant help within it, so I won't rewrite that help here. This example assumes you have an Ajax Callback process named "GIVE_RAISE". The basic steps are as follows:
Import the plug-in into your application (if you have not already).
The most common way to invoke the plugin will be to raise a custom event. Hence, you should create a DA that is based upon a custom event. In this example the custom event is "giveRaise":
Add a True action of type "Invoke Ajax Callback":
View the help for each attribute to understand how they are used.
You can then raise the event with code as show below:
javascript:apex.event.trigger(document, "giveRaise", {"empno":"#EMPNO#","empnoCS":"#EMPNO_CS#"});
That is all the Javascript you need to know. The rest is handled by the plug-in. If you want to do additional processing, though, the plug-in also supports that. Simple change the "With Result Action" to invoke additional Javascript or to raise an additional custom event.
Returning to the Ajax Callback process, GIVE_RAISE...that process should provide a success message. This is also in the plug-in help, but I'll put it here for completeness:
begin
-- your code here
-- if successful...
apex_json.open_object;
apex_json.write('message', l_name || ' given ' || :P4_RAISE_PERCENT || '% Raise!');
apex_json.close_object;
exception when others then
htp.p('Invalid Employee');
-- *** also log the error
end;
If you like this post or plug-in...
let use know :). Leave a comment, hit the like button, send me a note written on a the rim of a Boyd Cycles carbon fiber gravel wheel. Whatever works for you.