Wednesday, March 20, 2013

Ajax calls in apex: examples

Just an example on the various ways to perform an ajax call in apex.

Setup:

I'm doing this on page 18. You can do this on any page of course, if you just adjust the page item name.
There is a tabular form on this page based on EMP, just to demonstrate getting the values from the ENAME column into an array.

On Demand process, called "demoProcess"

DECLARE
l_f01 VARCHAR2(200);
BEGIN
   FOR i IN 1..apex_application.g_f01.count
   LOOP
      l_f01 := l_f01 || apex_application.g_f01(i) ||',';
   END LOOP;
   l_f01 := rtrim(l_f01, ',');

   htp.p('P18_EMPNO: ' || :P18_EMPNO || 
         ' - X01: '    || apex_application.g_x01 || 
         ' - F01: '    || l_f01 );
END;

Javascript:

PLEASE NOTE: there are calls to "console.log" in the javascript code. These will write to the console. In Firebug this is found simply on the "console" tab. In IE however you might encounter javascript errors. If so, open up the "developer tools" with F12 and rerun the page. (I put developer tools in quotes because what passes for it in IE can hardly be called so. Don't dev in IE unless you really must.)
//To demonstrate using one of the fnn-arrays to get an array of data to the server.
//In this case all values in the ENAME column
var lArray = [];
$("td[headers='ENAME'] input:visible").each(function(){
   lArray.push($(this).val());
});
//---------------------------------------------------------------------
//htmldb_Get
//works in all versions, but has never been officially documented
var ajaxRequest = new htmldb_Get(null, 
                                 $v('pFlowId'), 
                                 'APPLICATION_PROCESS=demoProcess', 
                                 $v('pFlowStepId')
                                );
ajaxRequest.addParam('x01', 'Temporary Variable x01');
ajaxRequest.addParam('f01', lArray);
ajaxRequest.add('P18_EMPNO',$v('P18_EMPNO'));
//sync
//this is how this request is usually seen used
//a synchronous call will "lock" up the browser until the call has completed
var ajaxReturn = ajaxRequest.get();
console.log(ajaxReturn);

//async
//A method often overlooked, which will do the call asynchronous. 
//However, involves a bit more code and thus feels a bit more obscure than
// a jQuery alternative
ajaxRequest.GetAsync(function(pResponse){
   if(pResponse.readyState==4 && pResponse.status==200){
      console.log(pResponse.responseText);
   };
});
//---------------------------------------------------------------------
//jQuery post, async
//An alternative method which works where jQuery is included. 4.0 and up.
//By default this request is asynchronous, but if required can be made 
//asynchronous by adjusting the "async" param. See the docs!
//p_arg_names + values: for page items. Arrays!
var lArgNames = ['P18_EMPNO'],
    lArgVals  = [$v('P18_EMPNO')];

$.post('wwv_flow.show', 
       {"p_request"      : "APPLICATION_PROCESS=demoProcess",
        "p_flow_id"      : $v('pFlowId'),
        "p_flow_step_id" : $v('pFlowStepId'),
        "p_instance"     : $v('pInstance'),
        "x01"            : 'Temporary Variable x01',
        "f01"            : lArray,
        "p_arg_names"    : lArgNames,
        "p_arg_values"   : lArgVals
        },
        function(data){
           console.log(data);
        }
      );
//---------------------------------------------------------------------
//new apex.server namespace in 4.2, async
//This should be the preferred method starting from apex 4.2.
//It offers all the flexibility of jQuery, and it is well documented by the
//apex team. Here you do not have to specify parameters like p_flow_id, nor
//have to use p_arg_names/values. pageItems is a very useful addition aswell!
//Since you can freely change the parameters used for the jQuery call, you
//again can make the call synchronous if you would require so.
//Note that i provide the dataType parameter. apex.server.process will by
//default use "json", so if you just put out some text through your process
//you need to change this as otherwise you will encounter javascript errors.
apex.server.process('demoProcess',
                    {"pageItems":"P18_EMPNO",
                     "f01":lArray,
                     "x01":"Temporary Variable x01"
                    },
                    {"dataType":"text", 
                     "success":function(data){
                                  console.log(data);
                               }
                    }
                   );

23 comments:

  1. Hi, Tom. Your example was the first one that seemed to solve my problem, but something is not working. i have a proccess that uses apex_application.g_f01. When the proccess is defined as 'On Submit', it works fine. But if i define it as 'On Demand', apex_application.g_f01 is always empty. It seems that it gets filled at submit time. When I saw the first lines of your javascript code, i thought that was the answer. is that the purpose of that lArray?

    ReplyDelete
  2. the f01 array has to be filled up with values. In the javascript code lArray is passed in for f01. Right beneath where I declare this array there is a jQuery each loop over a set of input items, whose values will be pushed into the array. This works on submit without troubles because that all happens automatically because of the "name" attribute on those items, and apex will map it to that array. For ajax you need to do the manual step of putting the values into an array and providing it to the request in order to have those values server-side.
    Does that clarify it?

    ReplyDelete
  3. Hi Tom, I tried the apex.server.process example and filled the lArray properly:

    apex.server.process('Save f01 Array into the APEX session',{"f01":arr_f01},{"success":function(data){apex.debug('success');}});

    I call a Application Process which is a Ajax Callback function on the same site. I put debug outputs there to control the state of apex_application.g_f01(1);:

    da_debug('x: ' || apex_application.g_f01(1));

    It worked. BUT when I branch to a different page and do the exact same backend debug output it is empty, I have no idea why.
    Shouldn't it be stored for the session?

    ReplyDelete
  4. Sorry, got caught up in the session thing. apex_application.g_f01 has no APEX session, just a DB-session, and every processing / rendering has a new one, so the values are gone :-)

    ReplyDelete
    Replies
    1. That's correct, the f## arrays and x## items are only stored for one page view, so if you want to retain them you could use the apex collections. :-)

      Delete
  5. I have a long running process - if I submit the page to call it it timesout. I'm just changing this to simply call via js and provide no feedback on when it is complete....but would using an on demand process allow me to get around the timeout and provide feedback to the user via htp.p? Or will it also time out the same?

    ReplyDelete
  6. Hi, do you have a sample application whats you are trying to accomplish here? iam lost?

    ReplyDelete
  7. Hi ToM
    Calling an On Demand process with apex.server.process for fxx arrays greater than f20 fails with a signature error (f01 to f20 are OK). Not sure why there is this limitation since APEX_APPLICATION support G_F01 to G_F50.

    Jon

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. Tom,
    I have a question about Ajax calls via JavaScript on on an APEX 5 page.

    Using APEX 5 with Firefox ESR 38.2 and Oracle 11g.

    I have a small application in APEX 5 and I am trying to call an on-demand process via apex.server.process within a small JavaScript function on a page. However it seems that the code is NOT being executed and I am not seeing anything on my firebug console..



    What I have is a JavaScript function in the function and global declaration section of a page. This is the actual function:



    function myFunction(p_url,p_review_date,p_bsr_tracking_id) {



    if (!p_review_date)

    {

    var r = confirm("Upon clicking 'Ok' you agree that\nyou have read and reviewed the\nselected BSR package");



    if (r == true) {

    alert(p_bsr_tracking_id);



    // First update the date reviewed for the report, for compliance data tracking



    // HERE IS THE CALL TO DUMMY APPLICATION PROCESS



    apex.server.process ("DUMMY"

    ,{x01: p_bsr_tracking_id}

    ,{dataType:"text"}

    );

    alert("After the Ajax call!!") ;

    // Next open the new window showing the report to be viewed



    var a = window.open(p_url )

    }

    }



    else {

    alert("BSR Package has already been Reviewed");

    }



    }



    Here is a copy of the DUMMY application process:



    BEGIN



    logger.log(apex_application.g_x01);



    UPDATE Bsr_Tracking

    SET Date_Reviewed = SYSDATE

    WHERE Bsr_Tracking_Id = apex_application.g_x01;



    COMMIT;



    END;



    Do you see anything that would be causing this to NOT function?



    Thank you,



    Tony Miller

    Los Alamos, NM

    ReplyDelete
  10. Found issue, authorization scheme on on demand process was set to not allow public user to execute...

    Now just need to find a method in JavaScript function to refresh the calling interactive report..

    Thank you,

    Tony Miller
    Los Alamos, NM

    ReplyDelete
  11. These new iPhone apps, and all the smart phone apps are getting pretty cool. You can go into a store and buy something, find out what you're looking for, compare prices, and even ring for help from a floor clerk. In fact, the apps might even tell you when a sale is going on when you might be passing by out front. The restaurant industry is also starting to use apps for things like their menus, reservations, alerting the valet to get your car now, and alerting you as to when your table is ready. have a peek here

    ReplyDelete
  12. Information technology training is typically thought of as only being necessary for IT personnel in the trenches. This article discusses the importance of IT management training for adapting to new business technologies and identifying new technologies to add to your business strategies. mobile tracker

    ReplyDelete
  13. This will be a terrific blog, would you be interested in doing an interview about just how you developed it? If so e-mail me! 토토사이트

    ReplyDelete
  14. You should mainly superior together with well-performing material, which means that see it: One Shot Keto Reviews – It Is really Work

    ReplyDelete
  15. Bon oui et aussi non. Ouais étant donné que on trouve certaines sources qui probablement accusent de similaires . Non parce que cela n’est pas suffisant d’imiter ce qu’on peut retrouver avec des articles tiers et de l’interpréter autant simplement: facebook login

    ReplyDelete
  16. In-home surveillance or spy cameras can be useful in many circumstances. Cameras can be used while your home is being cleaned, for home-sitter services, for security reasons and to monitor care providers for your children. how to build a hidden campfire

    ReplyDelete
  17. I admire your work , thankyou for all the interesting posts . bet188

    ReplyDelete
  18. you have a excellent weblog here! do you wish to make some invite posts in my small blog? Buy steroids online

    ReplyDelete
  19. https://tpetrus.blogspot.com/2013/03/ajax-calls-in-apex-examples.html?showComment=1600083639917#c3864044523238076496

    ReplyDelete
  20. The use of the mobile web by consumers is expanding geometrically and businesses need to know how to meet this avalanche of consumers on their terms. Learn the best practices for a functional mobile website. Beyond engaging new customers, the total impact of a mobile-friendly website and solid mobile strategy on your existing customer base is huge. singapore top mobile app developer

    ReplyDelete
  21. Sands Casino and Hotel | San Manuel, NM
    SEGA MEGA 제왕카지노 MEGADRIVE. Play your favorite Sega Genesis games 카지노 at Sandown Casino in San Manuel. Sign up today septcasino to claim your welcome bonus!

    ReplyDelete