APEX Custom Sourced Help Text

APEX Custom Sourced Help Text

·

8 min read

Introduction

In a previous post, APEX Dynamic Inline Help, I showed you how to create dynamic in-line help text. In this post, I will describe an approach for providing help text (sourced from outside of APEX Builder) to display when the❓icon is clicked.

Why do we need Custom Help Text?

Two customers recently asked me if APEX allows you to source help text from a source outside of APEX Builder. The driver for this is that they want their end users to be able to manage help text in a separate APEX Application. Standard APEX help text must be entered in APEX Builder. This, together with the fact that there is currently no PL/SQL API to maintain APEX help text, rules standard APEX help out.

This means we need some way to intercept the standard help text and call some PL/SQL code to get the help from our own help text table.

💡
Calling PL/SQL code to get the help text opens the possibility of sourcing help text from anywhere (not just a custom table). For example, you could call a REST API to fetch the help text from a content management system.

Standard Page Item Help

Let's level set by understanding how out-of-the-box help works for APEX Page Items. To enable standard APEX Page Item help, you only need to enter some help text in the 'Help Text' item property.

Oracle APEX Page Item Help

After entering the help text, a❓icon appears to the right of a page item.

Oracle APEX Page Item Help Showing Help Icon

Clicking the icon then shows the help text you entered in APEX Builder.

Oracle APEX Page Item Help Showing Help Popup

Implementing Custom Help

I realize this approach may not be the most elegant. I will gladly update this post if anyone has a cleaner way of intercepting the standard help event.

Overview

My approach involves the following three steps:

  1. Design an Alternate Help text table.

  2. Display the❓icon for page items that require help.

  3. Intercept the standard event that fires when you click the❓icon, fetch our own help, and display it to the end user.

1 - Alternate Help Text Table

Let's start by creating a table to store our alternate help text. I have created a table called CUSTOM_APEX_HELP_TEXT, with the following columns:

Oracle APEX Help Text Custom Table

There is a unique index on HELP_KEY and LANGUAGE_CODE.

2 - Displaying the❓Icon

This part is easy; APEX already displays the help icon when you enter text in the 'Help Text' item property. The difference is that instead of entering the help text, we will enter a token or key that matches the HELP_KEY column in our table.

Oracle APEX Dynamic Page Item Help Token

This is what the end user sees:

Oracle APEX Dynamic Help Page Item with Question Icon for Help

3 - Detect Click on❓and Display Custom Help

For this step, we will create a Dynamic Action that fires whenever the user clicks on the❓icon. On page 0, create a Click Dynamic Action that fires when the .js-itemHelp class is clicked.

Oracle APEX Dynamic Help Page 0 Dynamic Action

Let's pause here and show you how I knew to choose the .js-itemHelp class and how I knew that the data-itemhelp attribute stored the APEX Page Item ID. I discovered this by inspecting the HTML for the❓icon displayed to the right of a page item. The applicable attributes are highlighted in green in the screenshot below.

Oracle APEX Dynamic Help Inspect Help Icon

The Dynamic Action calls a JavaScript function called cnHelpUtil.showHelp:

Oracle APEX Dynamic Help Page 0 Dynamic Action JS Function

The JavaScript function is created in a Static Application file and has the following code:

/**
* @namespace var cnHelpUtil = {};
**/
var cnHelpUtil = {};

/**
* @function showHelp
* @example cnHelpUtil.showHelp(this, 'ITEM');
**/
cnHelpUtil.showHelp = function (theEvent, helpTrigger) {
  // Stop the standard help functionality from running.
  theEvent.browserEvent.stopImmediatePropagation();
  let helpValue;
  // Determine if trigger was a Page Item or an IG/IR Column.
  if (helpTrigger == 'ITEM') {
    // For an APEX Page Item we can get the Item ID from the Attribute 'data-itemhelp'.
    helpValue = $(theEvent.triggeringElement).attr('data-itemhelp');
  } else {
    // For an IG or IR column we have provided the attribute 'cn-help-key' along with the help key.
    helpValue = $(theEvent.triggeringElement).attr('cn-help-key');
  }
  apex.debug.info("Trigger ", helpTrigger);
  apex.debug.info("Source ", helpValue);

  // Call an APEX Server Process to Fetch the Help Text.
  apex.server.process('FETCH_CUSTOM_HELP',
    {x01: helpTrigger,
     x02: helpValue},
    {success: function (pData) {
      // Display the Help Text.
      apex.theme.popupFieldHelp({title:'Item Help', helpText: pData.help_text});
    },
    error: function(e){
      console.log(e);
      apex.message.clearErrors();
      apex.message.showErrors([
        {
          type: "error",
          location: "page",
          message: 'Unable to get get Custom Help',
          unsafe: false
        }
      ]);
    },
    dataType: "json"
    }
  );
}
💡
apex.theme.popupFieldHelp is the same API the standard APEX Page Item help calls when displaying help text. This API could also be helpful in other situations. It displays whatever text you pass it in a popup and does not escape it.

The JavaScript function performs the following steps:

  1. Determine if the user clicked the❓icon from an APEX Page Item or an Interactive Grid or Interactive Report column. More on IG/IR Column help later in this post.

  2. Determine the help_key based on where the❓icon was clicked.

  3. Call an Application Server Process FETCH_CUSTOM_HELP to fetch the help text.

  4. Display the help text to the user.

The result looks and behaves exactly like the standard APEX help, except you can get the help text from anywhere.

Oracle APEX Dynamic Item Help End Result

💡
Don't forget to reference the Static Application file containing the JS function under Shared Components > User Interface Attributes > JavaScript File URLs. That way, it will be available on all of your APEX pages.

Oracle APEX Custom Help Reference JS File

The APEX Server Process called from the JavaScript function (FETCH_CUSTOM_HELP) is declared under Shared Components > Application Processes as follows:

Here is the source code for the package CN_CUSTOM_HELP:

💡
Remember, you don't need to restrict yourself to get the help text from a table. You can put whatever logic you want in the PL/SQL block. Also, note that this code should go in a PL/SQL Package.

Other APEX Help

Of course, there are other areas where you can add help to your APEX Applications. This section will describe these areas and options for sourcing your own help text.

Page Help

Page help is the easiest area to utilize your own help text. Out of the box, you can easily create a help page and region by following these instructions. This approach automatically sources help text from the 'Help' page property in APEX Builder.

You can easily change the help page created by the above instructions to fetch help text from your own source.

Interactive Grid Column

When you add help text to the Interactive grid column attribute 'Help Text', APEX will show an additional column in the Column toolbar where a user can access the help text.

Oracle APEX Standard IG Help Icon

I have spent some time looking into the code behind the IG Column toolbar and could not figure out an elegant way to inject my own code so that I could source my own help text. My less-than-elegant solution is to add a <span> to the IG column heading. This adds a❓icon to the right of the column heading and includes a data attribute that I can use to specify the help key to use when the user clicks the❓icon.

This is what it looks like to the end user:

APEX Dynamic Help IG Column end-user

This is what it looks like in APEX Builder. In this example, I have set the cn-help-key data attribute equal to COUNTY.

Oracle APEX Span in IG Column Heading

County<span class="fa fa-question-circle-o padding-left-sm" 
  cn-help-key="COUNTY" aria-hidden="true"></span>

I created a second Dynamic Action on Page 0 that responds to a user clicking on the attribute cn-help-key:

APEX Dynamic Help IG Page 0 Dynamic Action

The Dynamic Action calls the same cnHelpUtil.showHelp JavaScript function we used for APEX Page Item Help above. The only difference is that we pass the parameter 'IG_IR' to tell the function we call from an IG or IR Column.

APEX Dynamic Help IG Page 0 Dynamic Action JS Function

Interactive Report Column

Like an Interactive Grid, when you add help text to the column attribute 'Help Text', APEX will show❓icon in the column toolbar where a user can access the help text.

To add our own help, we can use the same approach for Interactive Report Columns as for Interactive Grid Columns. We must add the same <span> to the IR column heading. The same Page 0 Dynamic Action we used for Interactive Grid columns will also detect the click of the❓icon on the IR column and call the JavaScript function cnHelpUtil.showHelp to fetch the help text for the help key and display it to the end user.

APEX Dyanmic Help Interactive Report Columns

Conclusion

Ideally, APEX Builder would provide a property where you could provide a PL/SQL function for APEX to call when the user clicks the standard❓icon. This would apply to Page help, Page Item help, and IR & IG Column help.

Whenever a user clicks the❓icon, APEX calls the custom PL/SQL function, passing the current page item, the current session language, and a key/identifier you provide. Your PL/SQL function code could then source the help text from anywhere you want.

💡
I created an idea in the APEX Ideas App suggesting that this functionality be included in APEX. You can see it here.