Tuesday, September 1, 2015

IR Column Headings with HTML in APEX 5

Old and new world

This might be something for all of you that have used HTML in interactive report column headings .
It was a convenient way to break up long headings if you already knew the content was much smaller.
To give you an example think of a date field with format mask 'DD.MM.YYYY' and a column heading of 'Final Auditor Approval Date'.
Now compare the size of the content to the heading size, which is 10 characters to 27 characters, so you might be wasting a lot of real estate for this column.
One approach is to specify the column width and enable word wrap using css, but what if you wanted the column heading to wrap at a specific position?
Well you can play around with your css rule until you get the desired result or you simply embed an html line break into your column heading and I typically used the latter.
The minute you upgrade to APEX 5 there's a small caveat with this solution.
Let me show you an example of what I'm talking about:

Do you see the html characters in the column list when you click on the magnifying glass?
In APEX versions before 5 the tag was replaced by a blank, nowadays it's escaped.
APEX 5 has gotten way better responsive features than before, but what if even that isn't sufficient?

There's an app plugin for that

Having the immediate need to find a solution I decided to create a plugin to solve this issue.
While thinking of options one that quickly came up was using the "Single Row View Label" as I'm not using the "Single Row View" in any of my applications.
Below you see an example I used during testing:
I removed the line break from the "Heading" and then changed the "Single Row View Label" to include it. So the data is stored in the APEX Metadata and I should now be able to use it.

The plugin itself is a dynamic action plugin and puts a small JavaScript function into the page.
The function retrieves a JSON object with column ids and column headings and then iterates over the object replacing the heading. Below you find sample code for the function:
function de_itt_apexir_hdr_break()
{ apex.server.plugin
  (
    '#AJAX_IDENT#' // This gets replaced by apex_plugin.get_ajax_identifier
  , { x01: this.affectedElements[0].id } // IR id
  , { success: function( pData ) 
               { apex.jQuery.each
                 ( pData, function(index, value)
                   { apex.jQuery("#" + index + " > a").html(value); }
                 ); 
               }
    }
  );
};

The callback function runs following query to compose the JSON object:
SELECT 'C' || aapic.column_id column_id
     , aapic.form_label
  FROM apex_application_page_ir_col aapic
     , apex_application_page_regions aapr
 WHERE aapic.region_id = aapr.region_id
   AND aapr.application_id = apex_application.g_flow_id
   AND ( aapr.region_id = to_number( regexp_substr( apex_application.g_x01, '\d+') )
      OR aapr.static_id = apex_application.g_x01
       )
   AND aapic.report_label != aapic.form_label
;

So far my tests didn't show any negative impact except for the obvious extra round trip to the database. Below screenshot shows same IR as before but using the plugin.


Want to test the plugin?  Download it here and install like any other plugin.
Follow the included readme file to create a dynamic action based on the plugin.
I haven't run that many tests yet, but maybe you would like to help?
If you encounter any issues or have recommendations, either open an issue in the repository or write a comment here.

Hopefully the plugin helps you to overcome one of the small hick-ups when upgrading to APEX 5.