Just a quick note that (as mentioned by Christian Neumueller earlier) APEX 5 now populates an Application Context APEX$SESSION
with the session’s User, Session ID and Workspace ID:
SYS_CONTEXT('APEX$SESSION','APP_USER')
SYS_CONTEXT('APEX$SESSION','APP_SESSION')
SYS_CONTEXT('APEX$SESSION','WORKSPACE_ID')
Using the above should be faster in your queries than calling v() to get these values. Note that the alias 'SESSION'
won’t work like it does with v().
The context is managed by the database package APEX_050000.WWV_FLOW_SESSION_CONTEXT
which is an undocumented API used internally by APEX to synchronize the context with the associated APEX attibutes. Incidentally, the comments in the package indicate it was authored by Chris himself.
Personally I was hoping that a bit more of the session state would be replicated in the context, e.g. application ID, page ID, request, debug mode, application items and page items.
Sidebar: to see all contexts that are visible to your session, query ALL_CONTEXT
. To see all context values set in your session, query SESSION_CONTEXT
. Of course, don’t query these in your application code to get individual values – that’s what the SYS_CONTEXT
function is for.
You have a Select List item on your page driven from a dynamic query, e.g. one that only shows valid values. One day, users notice that the list appears empty and raise a defect note.
You check the query behind the list and verify that indeed, the list should be empty because there are no valid values to show. It’s an optional item so the user is free to save the record if they wish.
There are a number of ways we could make this more user-friendly: depending on the specifics of the situation, we might just hide the item, or we might want to show an alternative item or a warning message. We can do any of these things quite easily using either a computation on page load (if the list doesn’t change while the page is open) or a dynamic action.
In the case of my client, they wanted the item to remain on screen, but to show an orange warning message to let them know that there are no gateways currently available; this is only a warning because there are subsequent processes that can handle the missing gateway (e.g. a higher-privileged user can assign a “hidden” gateway to the record if they deem it suitable).
To do this we create a display item (e.g. “P1_NO_GATEWAY_WARNING” which shows the warning message) and a dynamic action with the following attributes:
- Event = Page Load
- Condition = JavaScript expression
- Value =
listIsEmpty("P1_GATEWAY_ID")
- True Action = Set Value
- Set Type = Static Assignment
- Value = Warning: no gateways currently available
- Selection Type = Item(s)
- Item(s) = P1_NO_GATEWAY_WARNING
In the page’s Function and Global Variable Declaration, or (even better) in the application’s global javascript file, we add the following:
function listIsEmpty(itemName) {
return $("#" + itemName + " option:enabled").filter(
function(){return this.text;}
).length==0;
}
This was adapted from some solutions here. It looks for all <option>s under the item, filters the list for options which are not disabled and have a label, and returns true if the remaining set is empty. I added the this.text
bit because the empty lists generated by Apex include a single empty option for the “NULL” value. This is because I have set the list item’s Null Display Value to blank (null).
Quite a long time ago I made a collection of MP3s available from our APEX website and made them playable within the browser using Google’s shockwave player, using code like this:
<embed type="application/x-shockwave-flash"
flashvars="audioUrl=#FILE_URL#"
src="/3523697345-audio-player.swf"
width="400"
height="27"
quality="best">
</embed>
This relies on the user’s browser being able to run flash applications. It looked like this:
With HTML5, however, this is no longer required, so I’ve updated it to:
<audio controls preload>
<source src="#FILE_URL#" type="audio/mpeg">
</audio>
Not only is it simpler and no longer requires flash, it looks much nicer as well:
Note: you may or may not want to include the preload
tag, especially if you have more than one audio control on a page.