Wednesday, 17 May 2017

APEX 5.1 Interactive grid row processing and dynamic actions

APEX 5.1 IG processing

Interactive grid row processing and dynamic actions

IG row based DA tips

You started working with IG and wanted to implement dynamic actions within your IG report region.

Idea here is: You have a column in IG that triggers a change and DA fires and retrieves data from database before displaying them in your row columns.

There is a mini catch that I had issues figuring out - why and where hence this post. 

If you start googling about APEX IG most likely you will end up in good hands of John Snyder and his "how to hack APEX IG" series. Excellent material and heaps of useful things you might need along the way. 

The one that was of most help to me was Christoph's blog. Gives you a basic idea how to manipulate IG rows and change values.

Now that you have all the material it is time for implementation. 

First thing is to create your interactive grid (including a static ID). Second step select a column on which you want a DA to trigger. Create a DA with JS below. Third step is creating a page process that will return values from database. 

My process GETDOCINFO is: 
   r_doc_info varchar2(150);    
-- This should be getting the cached document info
r_doc_info:= get_info(APEX_APPLICATION.g_x01);
        apex_json.write('id', 'DOC_ID');
EXCEPTION when others then

As you can see it is pretty basic example. 

Now to the JavaScript bit.
//SET IG ROW details to be used in a fnc
//if this is removed IG row/model can not be retrieved
var p_element = this.triggeringElement;
var p_rowId = $(this.triggeringElement).closest('tr').data('id');

var dID;

        x01: this.triggeringElement.value //PASSING IN doc_ref
    }, {
        success: function(data) {
            var i, item;
  // this handles the page items to return set by the server process
 // data result is object with property item which is an array of page item id, value pairs
            if (data && data.item) {                  
                for (i = 0; i < data.item.length; i++) {
                    item = data.item[i];
                    dID = item.docID;
            } //end if        
            //Update IG columns
        } //success

//notice how this is different from example in blog   
function set_IG (pID){
    //Get the link element that was clicked
    var $te = $(p_element);
    //Identify the particular interactive grid
    var ig$ = apex.region("event_docs").widget();
    //here you have to change to use static ID of your region

    //Fetch the model for the interactive grid
    var model = ig$.interactiveGrid("getViews","grid").model;

    //Fetch the record for the particular rowId
    var record = model.getRecord(p_rowId);
    model.setValue(record,"DOCUMENT_ID", pID);   

Only thing to keep in mind is in yellow lines. Without keeping a reference to a row and element triggering this DA you may start receive errors in your browser console toString property not found. Comparing to Christopher's example there is very little difference but original version simply was not working for me when being called from ajax callback as information about the row and model would be lost along the way

As example this JS below would not work: 
        x01: this.triggeringElement.value //PASSING IN doc_ref
    }, {
        success: function(data) {
            var i, item;
            if (data && data.item) {
                var dID,dName,dUrl;
                for (i = 0; i < data.item.length; i++) {
                    item = data.item[i];
                    dID = item.value;                   
            } //end if          
        } //success

function set_IG (pID){

    //Get the element that was changed
    var $te = $(this.triggeringElement);
    //Get the ID of the row
    var rowId = $te.closest('tr').data('id');
    //Identify the particular interactive grid
    var ig$ = apex.region("event_docs").widget();
    //Fetch the model for the interactive grid
    var model = ig$.interactiveGrid("getViews","grid").model;
    //Fetch the record for the particular rowId
    var record = model.getRecord(rowId);
    model.setValue(record,"EVENT_DOCUMENT_ID", pID);   

Alternative approach would be to base your JS on rows selected and do processing from there. Something like: 

var view = apex.region("event_docs").widget().interactiveGrid(" getViews", "grid");
var records = view.getSelectedRecords();
//difference between input type and object like LOV
for ( i = 0; i < records.length; i++) {
    //if dealing with LOV for example
    console.log(view.model.getValue(records[i], "DOC_REFERENCE").v);
    //if dealing with regular text type for example
    console.log(view.model.getValue(records[i], "DOCUMENT_ID"));

Please note that there are heaps of different ways how to access data in IG model aim was only to bring to attention and what to keep an eye on.

This is all for now. Over and out.

Wednesday, 10 May 2017

APEX 5.1 migration mobile application

APEX 5.1 migration

Our experience going 5.1

Mobile Migration issues


The day has come to upgrade your system to APEX 5.1. This is a short post about things we encountered along the way. 

This post covers Mobile application version migration errors. There is a aeparate post for Desktop version.

Idea is to show case that even though it seems simple there might be more to it in terms of upgrade plans to 5.1.1 than you and I initially thought. You have been warned :)

1. problem - apex.server.process
Simple page when rendered would give this error
Uncaught TypeError: Cannot read property 'pageItems' of null
at i (mobile.min.js?v=
at h (mobile.min.js?v=
at Object.a.process (mobile.min.js?v=
at toggleFavourite (f?p=106:5:21::NO:RP,10:P5_STATION_CODE, P5_STATION_NAME,P5_SOURCE_PAGE:BA, Badgingarra,1:200)
at <anonymous>:1:1

The core of the problem was this JavaScript:
<script> function toggleFavourite() {
apex.server.process (
dataType: 'text',
success: function(isFavourite) {
if(isFavourite=='Y') $('#favouritebutton').addClass('favourite');
else $('#favouritebutton').removeClass('favourite');
} );
Solution: remove null, line and things worked again.

2. problem Invalid JSON.

Same process as in Problem 1. toogleFavourite contained this code:
Solution: this now became an invalid JSON as characters need a quotes htp.prn('"Y"'); Once this was replaced things worked again.

3. problem
- Map error

Uncaught ReferenceError: google is not defined
at HTMLDivElement.eval (eval at globalEval (jquery-2.2.3.min.js?v=, <anonymous>:39:20) at HTMLDivElement.e (jquery-2.2.3.min.js?v=
at HTMLDivElement.dispatch (jquery-2.2.3.min.js?v= at HTMLDivElement.r.handle (jquery-2.2.3.min.js?v=

By changing reference to a a Google JS library from inline on page to page template
sorted the problem. This probably has to do with JavaScript and exact timing of when a certain libraries are expected to be loaded. This was working fine in 5.0.

4. problem - Menu Error

In this application bigSlide menu JS library was used to implement a simple drop down menu. This was customization to the default apex template.

Menu did not work after Save
was clicked or any navigation happened in the application.


Problem was in a way APEX template work (since 4.2 version). If you are on page ID 1 and navigate to page ID 5 menu stops working because your page DOM holds more elements with same ID.

Why? Inspect your DOM when you navigate from page to page. You will notice that DOM things are being added as you move along.

<div id="P1" data-role="page" data-apex-page-transition="none" data-apex-popup-transition="none" data-theme="c" data-url......
<div id="P5" data-role="page" data-apex-page-transition="none" data-apex-popup-transition="none" data-theme="c" data-url......

We had a button on page 0 called Menu with static ID = rightpanel-link.   JavaScript was triggering on ID click which was now broken as multiple existed on same page.  

Work around apply logic but with the use of a classes.....

instead of ID based selectors
use class based selectors
5. problem - Menu display condition error
Server-side Condition was set to page is not in comma separated list of values that included 101 - Login page which cause the main menu not to be shown once you logged in. Menu would slide to the left but no content would be there.

Solution was to simply remove this condition and menu would work fine.

6. problem APEX Mobile link bug?

Page with a simple list that had a link to a certain page passing in few parameters. You would click on a link that takes you on next page but the URL of the new page is invalid as it was encoded by the engine. If you try refreshing the page you get APEX error. 

I tested this on and the same issue was there. This only happens in mobile version of UI. Not sure if this is a known thing or not. Currently we do not have a workaround.  

This is all for now. Over and out. 

Sunday, 23 April 2017

AUSOUG APEX 5.1 webinar series

Oracle APEX 5.1 webinar series

Australia/New Zealand ORACLE APEX webinars

Great speakers from USA, EU, AU and NZ

I am pleased to announce there is a huge interest not only among the speakers but also from the audience for this years 2017 AUSOUG APEX webinar series.
There is plenty of time for you to join us, please check AUSOUG Calendar for more details. First session is starting 27/04/2017 - registration.

Some of the speakers already confirmed

  • Dimitri Gielis, APEX RnD, Belgium
  • Tyson Jouglet, Skillbuilders, USA  
  • Scott Wesley, Sage Computing, Australia
  • Roeland Van den Eynde, APEX RnD, Belgium
  • Niels de Bruijn, MT AG, Germany
  • Oliver Lemm, MT AG, Germany
  • Aljaz Mali, Abakus Plus, Slovenia
  • Menno Hoogendijk, Qualogy, Netherlands
  • Matt Nolan, FOEX GmbH, Austria
  • .....more to come soon
in no particular order :)

More information on Hope to see you there.
Happy APEXing,

Monday, 10 April 2017

APEX 5.1 migration - compatibility tips

APEX 5.1 migration

Our experience going 5.1

Compatibility mode issues

The day has come to upgrade your system to APEX 5.1. This is a short post about things we encountered along the way. 

This post covers for Desktop application template version errors that uses compatibility mode 4.2. 

Idea is to show case that even though it seems simple there might be more to it in terms of upgrade plans to 5.1.1 than you and I initially thought. 

For mobile template errors there will be a separate post. 

Please note that I will be updating it as things pop up so watch the space.

1. First on the menu:

Ajax JS calls causing:
Ajax call returned server error ORA-20987: APEX - Session state protection violation: This may be caused by manual alteration of a URL containing a checksum or by using a link with an incorrect or missing checksum. If you are unsure what caused this error, please contact the application administrator for assistance. - Contact your application administrator. for .

If you dig into debug mode you would get some more details where APEX was listing what page item this problem occurred for. Bottom of the problem was some page items had Security attribute Session State Protection set to Check sum required - Session Level and were used in AJAX calls which now cause security errors to be shown. Solution of the problem was to change this as:

2. problem had to do with Old Custom Theme template and application that was running in 4.x compatibility mode.

Apex 4.x compatibility apps have an issue with the home breadcrumb not substituting values rendered URL looks like this:

How to fix this? One way is to chance this breadcrumb template from:

To this:
There are other ways how to do call this JS fix but for clarity of the blog I used "After Last" section.
3. problem - Dialogs for applications running in compatibility mode 4.x version

Front dialog not at correct z-index – unable to click on it due to modal click blocker being in front. Selenium tests still worked fine.
How to fix this? Add CSS style to your template
body .ui-dialog.ui-front{z-index:1001 !important} 

4. problem - Interactive report Filter Issue for 4.x compatibility mode
When you select Action-> Filter, Chrome console throws this error and it does not display filter options dialog screen:

First hint was this was related to old Classic Date Picker functionality that has been decommissioned.

This was confusing as on this IR there was no usage of Classic Date Picker or anything like that nor did the page contain any page items that were Date Pickers. Plus some IR of the same application were working perfectly fine while few others failed. This indicated that APEX 5.1 LS libraries were not the cause of the problem otherwise it would not have worked at all, right?

Solution: After significant amount of hours investigating, what narrowed it down was a desperate page export and comparison between working and non working IR page.

Core cause of all problems had nothing to do with Classic Date Picker nor with any JQuery conflict. It came down to bad programming practice and simple region Static ID set by developers. Pages where Filter action had an issue had ID set something similar to: 

I guess you see the problem straight away. What this invalid ID did it eventually broke JS functionality of IR as it was trying to use ID to handle user interactions. Once we updated IDs to include no spaces and less characters things were back to normal. All IR Filter actions started working again.

Hard lesson learned here. Only hint to APEX would be to add a check to static ID that it has to be a valid HTML ID for DOM element. Please note that same IDs in APEX worked perfectly fine. 

5. problem - apex.server.process error

Uncaught TypeError: Cannot read property 'pageItems' of undefined
at i (desktop.min.js:10)
at h (desktop.min.js:10)
at Object.a.process (desktop.min.js:10)
at Object.handleJson [as success] (map_rbgassessment.js:232)
at i (jquery-2.2.3.min.js:2)
at Object.fireWith [as resolveWith] (jquery-2.2.3.min.js:2)
at z (jquery-2.2.3.min.js:4)
at HTMLScriptElement.c (jquery-2.2.3.min.js:4)
at HTMLScriptElement.dispatch (jquery-2.2.3.min.js:3)
at HTMLScriptElement.r.handle (jquery-2.2.3.min.js:3)

Scenario: simple application page using this AJAX call

apex.server.process ("deletePins");

For deletePins application process:
Solution was to rewrite the AJAX call:

apex.server.process ( "deletePins", {
x01: "test",
pageItems: ""
}, {
success: function( pData ) {
console.log("(done) deletePins ");;
} );
Seems like call back needs to have a success handler.

6. problem - Download is showing additional column with URL details

Report on a page had SQL query for the source

  SELECT '<a href="javascript:apex.confirm(''Do you want to return this organism as a member?'', ''REVIVE_' || CARRIER_ID
  || ''');"><img src="#WORKSPACE_IMAGES#red-delete.svg" alt="revive" title="Revive Member"></a>'............

Export / Printing
Include In Export / Print
Yes/No -> set to NO defaulted to YES

7. problem - Internet explorer issue with Interactive reports and tabs

<meta http-equiv="X-UA-Compatible" content="IE=8" />
Check if your templates include the line above. This caused IE application to show heaps of related issues in DOM inspector.

Object doesn't support property or method 'submit'
and few others. By removing the line in yellow things were back to normal. Application was running template 24 in 5.0 compatibility mode. 

8. problem - Minor CSS class/DOM changes between APEX 5 and APEX 5.1

This caused some testing scripts to fail. Once you inspect the DOM you would notice small DOM changes and all you have to do is update your test scripts.

This is all for now. Over and out.

Last Update 27/04/2015

Latest update 03/05/2017