APEX 5 Event: theme42ready

A while aback I had a puzzle with setting the visibility of certain tabs on a carousel region.  Whether a tab displays or not depends on user selections on another page; based on those selections, I can hide or show a particular tab of the carousel.  The problem was, firing my hide/show dynamic action after Page Load was not doing it – the carousel seemed to complete its rendering after Page Load.  What?

I went to apex.world for suggestions. The solution was to fire my hide/show DA on the theme42ready event.
This event fires after page load … which is the event I needed.

How would I know such an event exists?

Luckily a friend in apex.word – Thank You Jeff Eberhard – clued me in.

theme42ready is triggered after the initialization of Universal Theme:

jQuery(window).on('theme42ready', function() {
log('Do something after UI elements are rendered on the page.');
});

I was then able to implement a dynamic action that first on event theme42ready – and got the result I expected.

There are two other Universal Theme events one should be aware of that may help in similar situations:

theme42layoutchanged  is triggered when left navigation menu is expanded or collapsed.

apex.jQuery("#t_TreeNav").on('theme42layoutchanged', function(event, obj) {
console.log('Left menu action: ' + obj.action); // obj.action will return expand or collapse
});

and
apexwindowresized is triggered when the APEX window is resized

apex.jQuery(window).on('apexwindowresized', function() {
console.log('Window resized.');
});

For more information on these events and other aspects of the Universal Theme, see the Universal Theme reference application. https://apex.oracle.com/pls/apex/f?p=42:6200:::NO:::

APEX Data Load Wizard Customizations ~ Revisited

dataLoadWizard
I was revisiting our APEX Data Load application, which uses a highly customized version of the APEX Data Load Wizard – several of them. Key words here: Highly Customized.

Customizing the Data Load Wizard – or modifying any set feature of APEX – leaves one open to the possibility that things might not work in the following versions. This has been the case with every major APEX upgrade since we made the Data Load Wizard customization in APEX 4.2.  Each time we have had to plan time/resources to revisit the customizations and make corrections – all on our own sleuthing.  No big deal, right?

This year an upgrade to APEX 5.1,  left the last step, the load into our defined Data Load table, not working. I had two choices, rebuild the Data Load Wizard pages ( 3 sets), and re-apply the customizations.  Or, write my own load into the final table.

This time I chose the latter.
As a quick reminder, the Data Load Wizard loads uploaded data into a series of collections.  To learn more about the Data Load Wizard and why we customized, read the previous Data Load Wizard posts. The data from those collections – after transformations are applied – gets loaded into the Data Load target table.  In our case, we needed complex validations and transformations, and logging of each change. The logging of each change is what really drove us to customizing the process. So we pulled data from the uploaded collection (SPREADSHEET CONTENT) into a temporary table, performed all our validations, transformations and logging, then moved the data back into the load collection (LOAD_CONTENT).  And continued with the Data Load process.  That’s a simplification, there are a lot of other pieces involved, but that’s enough for here. (Read previous blog posts for more details).

By choosing to write my own load into the final table, and bypass the APEX processes, I lose some other features that I now have to code on my own.  What I lose:

  • Automatic insert/updates
  • Automatics insert/update failure counts and logging.

I am OK with handling these in my own bulk process insert with the LOG ERRORS clause. We only get inserts, never updates, which simplifies things.  Your mileage may vary. Note that if you need to process updates and inserts, and report which records are inserted vs updated, the solution will be more complicated.

Next time we upgrade, I expect another set of minor Data Load Wizard changes … to which I will adjust somehow.  Now, IF the Data Load Wizard were to allow greater flexibility in logging transformations for each row – then I may be able to abandon the customized code altogether and revert to the mainstream Data Load Wizard.  Until then I am resigned to maintenance with each update.

P.S.
I just had someone ask about customizing the Data Load Wizard – breaking into the collections as I did. My recommendation was, use the Data Load Wizard to load into a staging table, then write PL/SQL processes to perform the validations needed – in his case to only do inserts no updates – filter out existing rows. Such a solution will be in-the-sandbox (no customizations) and will readily upgrade.
I strongly advise against breaking into the Data Load Wizard unless there is a solid business requirement to do so. Unless …

    • You have plenty of time to go back and fix things upon upgrade, and
    • You have a finding Fairy to pay for all those upgrades.

Happy Coding, whichever approach you choose.

APEX Interactive Grid: Customize Toolbar

APEX Interactive Grids allow customization of the Toolbar, the Grid Menu and the Column Heading options using JavaScript in the appropriate Grid or Column Attributes Advanced –> JavaScript Code element. This post discusses how to build a function to make simple changes to the Interactive Grid Toolbar.

widget.toolbar.js

The toolbar is implemented by a toolbar widget ,which is created by the interactive grid widget. To learn more about the toolbar widget, read library file widget.toolbar.js.  That file documents the properties of the toolbar widget,  the toolbarData array, control types and their properties.

toolbarData

toolbarData is an array that describes the toolbar – the buttons, fields and menus visible to the user, and their actions. Toolbar objects are grouped into control groups.  Each control group has one or more controls, of type Static, Text, Select, Button, Menu, Radio Group or Toggle.

By default, the toolbarData is based on the Grid default options and declarative settings.

Developers (you) can override the toolbarData property by adding a function to the Advanced–> JavaScript Code section of the Interactive Grid Attributes. Basically, you write a function that resets the toolbarData array to the configuration you want.

There are two general approaches to writing an override function:

  1. Totally replace
  2. Copy and adjust

That is, your custom configuration function can completely (re)define the toolbar, or, it can make adjustments to the default or current toolbarData.    Which approach is best depends on your requirements – the degree of customization required.

If you are totally replacing, you can fill the array as you want. You might want to examine the default toolbarData to see what is possible.

If you are adjusting, you need to understand the default toolbarData array to know where to add your customization.

Default toolbarData Array

By default, for an editable grid,  there are 7 control groups in the toolbar, as shown below:

toolbarDataArrayLabeled

Note that the reports, views, actions2 and actions3 toolbar groups are conditionally visible: the reports group becomes visible when there are multiple reports, the views group becomes visible when there are multiple views; the actions2 and actions3 groups become visible when edit mode is on.

To examine all of the elements in the toolbarData object (as well as all other objects of the interactiveGrid widget) use this command in the Console:

apex.region("emp_igrid").widget().interactiveGrid("option","config")

using the static id of your interactive Grid for “emp_igrid”. This command says, Show me the config options for the emp_igrid Interactive Grid region.

Examine the returned contents by clicking through all the objects.  Look at the toolbarData object, expanding the elements beneath it.  After a few clicks you will no doubt recognize menu and button elements of the interactive grid Actions menu and other toolbar features.

The default toolbarData array has 7 elements, for 7 control groups, shown below:

toolbarDataArray

If we look at just “actions1” object, you will see that it is a menu containing  the familiar elements of the Actions menu. This image shows the download dialog menu element expanded.

actions1Download

Let’s say our users do not like doing two clicks (Actions –> Download) to get to Download – they want a Download button on their toolbar.  In fact, they want it all the way over to the right.

To do this, we need to construct a JavaScript function to adjust the toolbarData to add a Download button in the actions4 (the rightmost) control group.

This function does the trick:

function(config) {
 var $ = apex.jQuery,
 toolbarData = $.apex.interactiveGrid.copyDefaultToolbar(),
 toolbarGroup = toolbarData.toolbarFind("actions4"); // this IS the rightmost GROUP WITH the RESET button

// add a Download button next to the Reset button
 toolbarGroup.controls.push( {
 type: "BUTTON",
 action: "show-download-dialog",
 iconBeforeLabel: true,
 hide: false,
 disabled: false
 });
 
 config.toolbarData = toolbarData;
 return config;
}

The toolbar stuff adds the button, with the action show-download-dialog.  The show-download-dialog action is the same definition found while examining the actions menu.

If you are a PL/SQL developer, and relatively new to JavaScript, the above JavaScript is very readable:

  • Copy the default toolbarData – we will make changes to a copy
  • Get the actions4 toolbar group
  • Add (Push) the download dialog to the actions4 toolbar group
  • Copy the modified toolbar to the return config

Very easy to follow.  But this is a very basic example.  If you will be doing a lot of such customization, pursue additional JavaScript training.  Hint: Remember that JavaScript is case sensitive, where PL./SQL is not.  That alone will save some grief.

Note that Download is a declarative option –

DeclarativeDownload

So, if/when a (the next?) developer sets Download Off … your newly-placed Download button disappears.  The declarative nature of the show-download-dialog action is contained within the action – our moving the button around does not overwrite that declarative toggle.

One can also turn off Download (and other features) programmatically. To do so, we use this command:

config.features.download = false;

as part of you Advanced –> JavaScript Code function, or in a dynamic action.  This command will also turn off your newly-placed Download button.

This simple example show how to add one button – you can of course add more, or redefine the entire toolbarData area.  For additional, more complex toolbar customization examples, see the examples in the Sample Interactive Grid packaged application.  And read the Interactive Grid posts in the HardLikeSoftware blog by John Snyders of the Oracle APEX team.

Interactive Grid is a great new region type – and it is still evolving. This writing is for APEX 5.1.2 – APEX 5.2 may bring more declarative options, and/or may bring documented APIs for customizing the toolbar – who knows.  Stay tuned!