Thursday, 21 July 2011

Application Express 4.1 - #BUTTON_ID# Changed Behaviour

I just wanted to blog about some changed behaviour that will be landing in APEX 4.1. The change has to do with the #BUTTON_ID# substitution string, available for use within a button template and we hope will have minimal impact.

What's Changing?

Prior to 4.1, the value substituted for the #BUTTON_ID# substitution string in a button template depended on the type of button:
  • Region buttons substituted the internal numeric ID of the button, for example '123456789101112'.
  • Item buttons actually failed to substitute this value at all, so you would just get the '#BUTTON_ID#' text.
We had to address and improve this for the new Dynamic Action / Button integration in 4.1, which means that the value substituted for #BUTTON_ID# will now be one of the following:
  1. If the template is used by an item button, the item name is used, for example 'P1_GO'.
  2. If the template is used by a region button and a 'Static ID' (new in 4.1) is defined for the button, this is used, for example 'my_custom_id'.
  3. If the template is used by a region button and no 'Static ID' is defined, an ID in the format 'B||[Internal Button ID] will be used, for example 'B123456789101112'.
The change in behaviour that could be of potential significance in your applications is #3 above. This was changed so as to be a valid HTML 4.01 identifier (begins with a letter) and to be consistent with how we handle other component IDs in Application Express. 


Will this impact your applications?

If you used a button template, that used an ID value substituted by #BUTTON_ID# (you would have had to add it to the button template, as this was never included by default in our themes), and importantly you hard-coded that ID from other places in your code (for example in custom JavaScript to attach behaviour to the button), then this change in behaviour will cause that code to no longer work.


What can you do about this?

To help you identify region buttons that use a template containing the #BUTTON_ID# substitution string, you can run the following query in your workspace in Application Express 4.0:

    select aapb.application_id,
           aapb.page_id,
           aapb.button_name,
           aapb.label,
           aapb.button_id,
           aapb.button_template,
           aatb.template
      from apex_application_page_buttons aapb,
           apex_applications aa,
           apex_application_temp_button aatb
     where aapb.application_id     = aa.application_id
       and aa.application_id       = aatb.application_id
       and aa.theme_number         = aatb.theme_number
       and aatb.template_name      = aapb.button_template
       and aapb.application_id     = [Your App ID]
       and aapb.button_template    is not null
       and aapb.button_position    = 'Region Position'
       and upper(aatb.template)    like '%#BUTTON_ID#%'
     order by 1,2,3

Or when APEX 4.1 comes out, you'll be able to do this (by virtue of the addition of the BUTTON_TEMPLATE_ID column to the APEX_APPLICATION_PAGE_BUTTONS dictionary view):

    select aapb.application_id,
           aapb.page_id,
           aapb.button_name,
           aapb.label,
           aapb.button_id,
           aapb.button_template,
           aatb.template
      from apex_application_page_buttons aapb,
           apex_application_temp_button aatb
     where aapb.button_template_id = aatb.button_template_id
       and aapb.application_id     = [Your App ID]
       and aapb.button_template    is not null
       and aapb.button_position    = 'Region Position'
       and upper(aatb.template)    like '%#BUTTON_ID#%'
     order by 1,2,3

This will not detect where you may have referenced the ID in other code (such as JavaScript code), it just identifies the buttons that could be problematic. So you can then review the pages returned by this query, to isolate any pages that could have issues. 

The easiest way to fix the issue will be to use the 'Button ID' value returned from the query as the new 'Static ID' for the button. This would mean the button would be rendered with the same ID as prior to release 4.1 and any dependent code would still work.

This will of course be documented in our Release Notes as Changed Behaviour, but I hope this post helps to give a little pre-warning as to whether this may affect you.

Updated: Thank you to Louis-Guillaume Carrier-Bédard for pointing out that the query I (rather stupidly!) initially added does not work in APEX 4.0. My apologies if this caused any inconvenience.

3 comments:

Louis-Guillaume Carrier-Bédard said...

Hi Anthony,

The query you provide to identify region buttons, that use a template containing the #BUTTON_ID# substitution string doesn't work with APEX 4.0.2.00.07.

ORA-00904: "AAPB"."BUTTON_TEMPLATE_ID": invalid identifier

Can you please provide a valid query for version prior to APEX 4.1? It will make things easier for everyone.

Thanks,
Louis-Guillaume

Arie Geller said...

Hi Anthony,

Thanks for sharing this important information.

Usually, the Changed Behaviour section in the Release Notes is the first thing I read, and as one who upgraded applications since 1.6, it almost always saves me precious time. However, I suspect that more people are reading your Blog than the Release Notes.

Regards,
Arie.

Anthony Rayner said...

Louis-Guillaume - Thanks for pointing this out, I should have realised that. Updated post with a query that'll do the job in 4.0, with due credit! Apologies for this.

Arie - No problem!! Regarding your comment, people should switch to reading the Release Notes more than MY blog, as they would probably have more frequently updated reading material (based on the infrequency of my posts!!).