Skip to Main Content

APEX

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

Pass value to and from a callback process

David BergerNov 1 2017 — edited Nov 6 2017

Hi, I need your help.

I would like to know how it is possible to pass a value (parameter) to a plsql callback process and how I can get a result back to javascript.

I have two text items (P_TEXT_IN, P_TEXT_OUT) and a button (BUTTON) and a test case:

var $wP;

var displayError = function(error) {

    console.error("Promise is rejected:", error);

};

var call_block1 = function() {

    $wP = apex.widget.waitPopup();

    return "End of Block 1";

};

var call_block2 = async function() {

    return apex.server.process( "MY_CALLBACK", {x01: "#P_TEXT_IN", pageItems: "#P_TEXT_IN"}, {refreshObject: "#P_TEXT_OUT"} );

};

var call_block3 = function() {

    $wP.remove();

    return "End of Block 3";

};

async function call_refresh() {   

    try {

        var result1 = await call_block1();

        console.log('Phase: ', result1);

        var result2 = await call_block2();

        console.log('Phase: End - Block 2');

        var result3 = await call_block3();

        console.log('Phase: ', result3);

    } catch(e) {

        $wP.remove();

        console.error(e);

        alert('Error!');

    } finally {

        console.log('Do something no matter what');

    }

};

call_refresh();

// Here I need the value of "v_result" from plsql....

The Callback Process "MY_CALLBACK":

DECLARE

   v_parameter_in   VARCHAR2(100);

   v_result         VARCHAR2(100);

BEGIN

  v_parameter_in := APEX_APPLICATION.G_X01;

  SELECT v_parameter_in || '-COMPLETED'

    INTO v_result

    FROM DUAL;

     -- This does not work... WHY?

  :P_TEXT_OUT := v_result;

    apex_json.open_object;

    apex_json.write('success', true);

    apex_json.write('v_result', v_result);

    apex_json.close_object;

END;

Question:

How can I get back the value of the variable "v_result" from my plsql?

Thanks in advance!

This post has been answered by David Berger on Nov 2 2017
Jump to Answer

Comments

David Berger

Hello, is it so hard to solve it? Nobody knows the answer? How do you solve this problem, I am sure that you use plsql in your apex application and you need to pass some result-values back to the javascript. How do you do this? Thanks.

Bharat G

Hi David,

Am not much into Java Scripts, So I followed below process for this kind of similar problem to achieve immediately.

1. Created 1 hidden Item.

2. Create Dynamic Action for button (Button Click Event)

  2.1. Create Action-1 for PLSQL(Execute PL/SQL Code) and call the PLSQL what we need and get the output of that PLSQL to that hidden variable

  2.2. Create Action-2 for JavaScript (Execute JavaScript Code) and call the javascript whatever we need using the above hidden variable which contains PL/SQL Output.

Regards,

Bharat

Neil Clare

You need to add a success callback to your apex.server.process call.

Something like

success: function( pData ) {alert(pData.v_result);}

pData will contain the JSON output from your PL/SQL process.

Pavel_p

Hi David,

as already suggested, use the standard JS API https://docs.oracle.com/database/apex-5.1/AEAPI/apex-server-namespace.htm#GUID-45B43DB1-9601-4BD6-9B7C-6C41C35BEE49 (you can specify the waiting spinner in it as well). Let's assume you have everything on page 5, so create a dynamic action Execute JS code:

apex.server.process ( "MY_CALLBACK", {

  x01: $v("P5_TEXT_IN") // ,pageItems: "#P5_TEXT_OUT" this item is being set in the process

  }, {success: function( pData ) {

      alert("process finished successfully, P5_TEXT_OUT will be set now.");

      var ajaxResult = pData;

      var succ  = ajaxResult.success; //not needed

      $s("P5_TEXT_OUT",ajaxResult.v_result );

      

      }

      } );

and a slightly modified code for your PL/SQL process (added debug messages):

DECLARE 

    v_parameter_in   VARCHAR2(100) := APEX_APPLICATION.G_X01; 

    v_result         VARCHAR2(100); 

BEGIN 

    apex_debug.message('DEBUGMSG: MY_CALLBACK was invoked with input parameter %s', v_parameter_in);

    v_result := v_parameter_in || '-COMPLETED'  ; 

    apex_debug.message('DEBUGMSG: v_result is %s', v_result);

     -- This does not work... WHY? 

    apex_debug.message('DEBUGMSG: P5_TEXT_OUT before assignment %s', :P5_TEXT_OUT);

    :P5_TEXT_OUT := v_result; 

    --it does work but it sets the value only in the session state (you would need to reload the page to see changes in the browser)

    apex_debug.message('DEBUGMSG: P5_TEXT_OUT after assignment %s', :P5_TEXT_OUT);

 

    apex_json.open_object; 

    apex_json.write('success', true); 

    apex_json.write('v_result', v_result); 

    apex_json.close_object; 

END;

In the process P5_TEXT_OUT item is being set, only in the session state (e.g. server side) and the client does not know anything about this change until the page is reloaded. So you need to process the returned JSON (pData) and set the value in JS ($s is a shortcut for https://docs.oracle.com/database/apex-5.1/AEAPI/apex-item.htm#AEAPI29496 ).

Regards,

Pavel

David Berger
Answer

Hello, thank you all for your replies.

I have learnt a lot again.

Here is my solution which works very well:

In a dynamic action of a button:

var $wP;

var displayError = function(error) {

    console.error("Promise is rejected:", error);

};

var call_block1 = function() {

    $wP = apex.widget.waitPopup();

    return "End of Block 1";

};

var call_block2 = async function() {

    return apex.server.process( "MY_CALLBACK", {pageItems: "#P_TEXT_IN"}, {dataType: "text"} );

};

var call_block3 = function() {

    $wP.remove();

    return "End of Block 3";

};

async function call_refresh() {  

    try {

        var result1 = await call_block1();

        console.log('Phase: ', result1);

        var result2 = await call_block2().then(function(pData) {

                              var v_result = JSON.parse(pData).result;

          

                              if (JSON.parse(pData).success == true){

                                    apex.item("P_TEXT_OUT").setValue(v_result);

                                    alert("Success! Result = " + v_result);

                              } else {

                                    alert("Error! " + v_result);

                              }});

  

        console.log('Phase: End - Block 2');

        var result3 = await call_block3();

        console.log('Phase: ', result3);

    } catch(e) {

        $wP.remove();

        console.error(e);

        alert('Error!');

    } finally {

        console.log('Do something no matter what');

    }

};

call_refresh();

In the callback process:

DECLARE

   v_parameter_in   VARCHAR2(100);

   v_result         VARCHAR2(100);

BEGIN

  v_parameter_in := :P_TEXT_IN;

  SELECT v_parameter_in || '-COMPLETED'

    INTO v_result

    FROM DUAL;

    apex_json.open_object;

    apex_json.write('success', true);

    apex_json.write('result', v_result);

    apex_json.close_object;

   

EXCEPTION WHEN OTHERS

THEN

    apex_json.open_object;

    apex_json.write('success', false);

    apex_json.write('result', SQLERRM);

    apex_json.close_object;

END;

Thank You all again! Regards, David

Marked as Answer by David Berger · Sep 27 2020
David Berger

Hello Pavel,

Your solution is very good if it runs only in a normal mode.. but in my environment where I run the server-side process as an asynch function there I can not implement your solution directly.

I need the ".then"-Construct as you see in my solution. Thanks anyway.

Pavel_p

David, may I just ask if you cannot use a PL/SQL (or eventually Set Value) DA with Wait for Result attribute =No without any JS involved? It seems that it could be pretty close to your requirements.

David Berger

Hi Pavel, of course it is just an example.. in the real code stands a statement-execution of a Materialized View which can take 10-20 seconds long.

Pavel_p

Hi David,

I still don't see the difference between the built-in DA with Wait for Result attribute =No and your JavaScript, but it does not matter, I don't have to necessarily understand everything.

It looks like a long-running process and as such it should not probably be run from JS anyway (today it's 10-20 secs, tomorrow it could be 2 minutes). In APEX < 5.1 we used to have https://docs.oracle.com/cd/E37097_01/doc.42/e35127/GUID-76D4B96A-9609-4587-B095-A512970493A2.htm#AEAPI1203 that was unfortunately removed in 5.1 with no decent replacement. This https://blogs.oracle.com/apex/run-plsql-in-background-and-display-a-progress-bar is the recommended way how to execute long-running background processes nowadays.

Regards,

Pavel

David Berger

Hi Pavel, wow! This approach is very good. Thank You!

The process must be run in the background and the user must be locked till the end of the process - so Wait for Result should be Yes but it does not work... because I need to exeucte some javascript before and after and this order I can not realize because of the synchronous execution of javascript statements.

1 - 11
Locked Post
New comments cannot be posted to this locked post.

Post Details

Locked on Dec 4 2017
Added on Nov 1 2017
11 comments
10,818 views