Friday 9 May 2014

Oracle APEX - Disappearing Popup Key LOV descriptions

Popup Key LOVs are really useful, but ...

Popup Key LOV items let you have a page item that has an ID column as its source but which displays a text value in its place. Like this:

The SQL behind the LOV looks something like:

SELECT display_name d, id r
  FROM source_table
 ORDER BY 1
You can use them in forms and (as above) in tabular forms, but there's a bug when used in tabular forms that has been around for a few versions, and is still present in APEX 4.2.

The Problem

If you use the Add Row feature to create a blank record, then select a value from the Popup Key LOV and then Save Changes, if you have any validation processes that cause in-line error messages to be displayed, this causes the displayed value for the Popup Key LOV item to disappear. The selected ID value is still in the DOM, but the display value does not get re-rendered.

The Workaround

The idea is to scan the tabular form on Page Load, looking for Popup Key LOV items that have an ID value but do not have an associated display value, and call an AJAX function to retrieve the display value.

Limitations of this solution

In my case the Popup Key LOV is based on a named LOV. I use this name to retrieve the SQL for the LOV from APEX and execute it via AJAX. This means that the SQL is only defined once, in the LOV.

The code below is generic, apart from the Dynamic Action, for which you need to provide the name of the LOV. I only have one LOV item in my tabular form so the LOV name can only be one value. This could probably be derived from APEX views but I haven't done that here.

Dynamic Action

  • Event: Page Load
  • Condition: no condition
  • Action: Execute Javascript code
  • Code:
// Find any LOV items that have an ID value but do not have an
// associated display value. This will happen if new records have
// been added and there is an inline error displayed when the page
// is submitted.
// - <input type="hidden"> is the hidden ID value for the LOV
// - <input type="text"> is the displayed value
// - 'UIN_LOV' is the name of the named LOV for this item
$('span.lov').each(function(){
  var vID = $(this).find('
input[type="hidden"]');
  var vVal = $(this).find('input[type="text"]');
  if($(vVal).val()==""){
    $(vVal).val(get_LOV_value('UIN_LOV',$(vID).val()));
  }
});

Javascript

//////////////////////////////////////////////////////////////
//
// Get the display value from an LOV for the supplied ID
//
// This is used primarily when an inline error is displayed and
// there are Popup Key LOV items displayed in a tabular form.
// In this case APEX does not display the return values for
// the Popup Key LOVs on any newly added records.
//
function get_LOV_value(pLOV,pId){
  var get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=get_LOV_value',0);
  get.addParam('x01',pLOV);
  get.addParam('x02',pId);
  return get.get();
}


Application Process

  • Process Point: On Demand
  • Type: PL/SQL Anonymous Block
  • Source:
DECLARE
  v_sql VARCHAR2(32767);
  v_val VARCHAR2(32767);
  CURSOR c_lov_sql IS
    SELECT list_of_values_query
      FROM apex_application_lovs
     WHERE application_id = :APP_ID
       AND list_of_values_name = apex_application.g_x01;
BEGIN
  OPEN c_lov_sql;
  FETCH c_lov_sql INTO v_sql;
  CLOSE c_lov_sql;
  v_sql := 'SELECT d '
         ||' FROM ('||v_sql||')'
         ||' WHERE r = '||apex_application.g_x02;
  EXECUTE IMMEDIATE v_sql INTO v_val;
  htp.prn(v_val);
EXCEPTION
  WHEN OTHERS THEN
    htp.prn(SQLERRM);
END;

                        Thursday 3 May 2007

                        TiddlyLockPlugin - the multi-user TiddlyWiki Plugin

                        When I wrote (i.e. hacked) TiddlyLock, I didn't realise just how simple plugins for TiddlyWiki were to write. All the examples I had seen looked really complicated and had lots of /*** ***/ !!! and //{{{ characters in them and I couldn't tell what was required and what wasn't. See my previous post for an example of how simple plugin are, and how quickly they can become difficult to read!

                        Anyway, the first version of TiddlyLock was a JavaScript hack - I modified the core code directly.
                        <smackhand>ouch
                        I'm a reformed citizen now and have re-coded TiddlyLock into TiddlyLockPlugin, the self-contained, easy-to-install, set-and-forget plugin that allows multiple people to access and edit the same TiddlyWiki file on a shared drive, but prevents users from overwriting each other's changes.

                        Simply use the ImportTiddlers tiddler in your TiddlyWiki (look for it on the Shadowed tiddlers tab) and point it to http://www.minormania.com/tiddlylock/tiddlylock.html. Select TiddlyLockPlugin and import it.

                        Reload your TiddlyWiki and set the Username and Password options in the OptionsPanel or in the GettingStarted tiddler.

                        Now, every time you click Edit the TiddlyWiki will be locked by you. Any other user who tries to edit the same TiddlyWiki will be told that you are locking it. They will have to wait until you are finished and refresh their browser before they can edit it.

                        It's not foolproof, and 'passwords' are visible and unencrypted, so don't expect enterprise-level security.

                        To Do:

                        • Obfuscate passwords
                        • Encrypt lock file

                        Tuesday 1 May 2007

                        TiddlyWiki - How to Write a Plugin

                        There are lots of plugins available for TiddlyWiki, but documentation on how to actally write a plugin is scarce. I understand the concept - plugins are just tiddlers that contain JavaScript and are tagged with "systemConfig" - but I couln't find any explanation of the syntax of a plugin and simple instructions on how to get it to work.

                        So, here it is. And it's really simple.

                        • Create a New Tiddler by clicking on the "new tiddler" link in your TiddlyWiki
                        • Choose a name for your plugin (tiddler) - standards say you should end the name with the word "Plugin". e.g. TiddlyLockPlugin
                        • The body of the tiddler at it's simplest is just straight JavaScript
                        e.g.
                        alert('Hello, World');
                        • You can add standard TiddlyWiki content as well to provide some comments, usage info and other supporting documentation. This text must be 'commented out' using the standard JavaScript commenting characters // or /* ... */ remember, the content of the tiddler is interpreted as JavaScript
                        • You should also surround your JavaScript code with {{{ and }}} to allow it to be displayed by TiddlyWiki without being interpreted by the browser.
                        e.g.
                        /***
                        this is the Hello, World plugin
                        |Hello, World|a simple sample plugin|
                        !!! here comes the code ...
                        ***/
                        {{{
                        alert('Hello,World');
                        }}}

                        • Include "systemConfig" as one of the tags for the tiddler.
                        • Save your tiddler and reload the TiddlyWiki. The 'Hello, World' alert box should appear.
                        And that's it!

                        Thursday 26 April 2007

                        TiddlyLock:- the multi-user TiddlyWiki

                        I use TiddlyWiki as a scrapbook, for storing notes, code samples, hints and tips that I can easily copy & paste into other projects.

                        I recently wanted to use it as a team development tool but soon found out that it is really only a single user tool.

                        So I modified it and created TiddlyLock.

                        This modified version of TiddlyWiki is based on TiddlyWiki 2.1.3 and it creates a lock file (based on the TiddlyWiki file name) whenever someone edits the TiddlyWiki, and unlocks it once all changes have been saved. Other users who try to edit the TiddlyWiki at the same time will get a message saying who has the file locked. Other users will have to wait until the TiddlyWiki is unlocked and reload it before they can edit it.
                        Users are identified by Username and Password.

                        Because this modification was done simply to enable a team of developers to use the same TiddlyWiki without running the risk of editing it at the same time and potentially overwriting each other's work, there is currently no password encryption and passwords are visible in clear text. We're a trusting bunch ;)

                        If you'd like to try it out, save this link to your computer (if you open the link in your browser it will be restricted to read-only mode - you have to save it locally in order to be able to edit it)

                        If you're looking in the code for my changes, my object names (variables, functions, etc) are prefixed with "TL", so just do a case-sensitive search and you'll have 'em all.

                        Hope this is useful to you.