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);
                               }
                    }
                   );

2 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