# APEX Custom Sourced Help Text

# Introduction

In a previous post, [APEX Dynamic Inline Help](https://blog.cloudnueva.com/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.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">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.</div>
</div>

# 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](https://cdn.hashnode.com/res/hashnode/image/upload/v1696116860042/fbf63403-8e47-4e12-af36-4cfabd3b0d30.png align="center")

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

![Oracle APEX Page Item Help Showing Help Icon](https://cdn.hashnode.com/res/hashnode/image/upload/v1696117030779/01b10e92-ed5e-470a-aeb6-598d564fee65.png align="center")

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

![Oracle APEX Page Item Help Showing Help Popup](https://cdn.hashnode.com/res/hashnode/image/upload/v1696117147061/06b33633-d6b8-477d-b260-2cf2f1e0602f.png align="center")

# Implementing Custom Help

<div data-node-type="callout">
<div data-node-type="callout-emoji">⚠</div>
<div data-node-type="callout-text">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.</div>
</div>

## 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](https://cdn.hashnode.com/res/hashnode/image/upload/v1696118204034/2e5b87b5-e925-4b35-a34f-fd739b958b83.png align="center")

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](https://cdn.hashnode.com/res/hashnode/image/upload/v1696117621972/c49af801-83ff-45da-95be-f8b635e97271.png align="center")

This is what the end user sees:

![Oracle APEX Dynamic Help Page Item with Question Icon for Help](https://cdn.hashnode.com/res/hashnode/image/upload/v1696269254321/5f3f77ce-8512-4294-9ca9-d231d6dd6784.png align="center")

## 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](https://cdn.hashnode.com/res/hashnode/image/upload/v1696809407241/d21943ec-68ea-458c-a900-11e7db70c488.png align="center")

> 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](https://cdn.hashnode.com/res/hashnode/image/upload/v1696119722922/449a23b9-f448-4a9c-bea2-b9674a4c387f.png align="center")

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

![Oracle APEX Dynamic Help Page 0 Dynamic Action JS Function](https://cdn.hashnode.com/res/hashnode/image/upload/v1696809494997/ddf15dd4-5381-46aa-8c04-223b47ebe048.png align="center")

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

```javascript
/**
* @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"
    }
  );
}
```

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><a target="_blank" rel="noopener noreferrer nofollow" href="https://docs.oracle.com/en/database/oracle/apex/23.1/aexjs/apex.theme.html#.popupFieldHelp" style="pointer-events: none">apex.theme.popupFieldHelp</a> 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.</div>
</div>

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](https://cdn.hashnode.com/res/hashnode/image/upload/v1696127646059/d5875173-5248-4b05-8129-789603928661.png align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Don't forget to reference the Static Application file containing the JS function under Shared Components &gt; User Interface Attributes &gt; JavaScript File URLs. That way, it will be available on all of your APEX pages.</div>
</div>

![Oracle APEX Custom Help Reference JS File](https://cdn.hashnode.com/res/hashnode/image/upload/v1696811297849/3443d092-1496-41bb-99e7-bfcb42b6b11b.png align="center")

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1696810372708/d25ee396-bed1-418e-aa87-fd03840c3aa8.png align="center")

Here is the source code for the package `CN_CUSTOM_HELP`:

%[https://gist.github.com/jon-dixon/b632a66cb66ca201f181709b78d55e69] 

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">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.</div>
</div>

# 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](https://docs.oracle.com/en/database/oracle/apex/23.1/htmdb/creating-help-for-your-application.html#GUID-06145226-27F3-4D70-8BAA-2967EB0B45A1). 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](https://cdn.hashnode.com/res/hashnode/image/upload/v1696167910386/7c2e92ea-8690-442c-ac1f-9653393a1324.png align="center")

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](https://cdn.hashnode.com/res/hashnode/image/upload/v1696266868551/1cc10ae2-2e5e-4e78-8b9a-e687dfdd6987.png align="center")

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](https://cdn.hashnode.com/res/hashnode/image/upload/v1696266722782/0480b166-b51c-4d24-bcd0-cbc98059d139.png align="center")

```xml
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](https://cdn.hashnode.com/res/hashnode/image/upload/v1696810584388/72c11734-ac1c-490b-ae38-b52dd5599de6.png align="center")

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](https://cdn.hashnode.com/res/hashnode/image/upload/v1696810677825/74a2a3cf-fd1b-4fd5-b344-9f64eee50d52.png align="center")

## 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](https://cdn.hashnode.com/res/hashnode/image/upload/v1696267693146/4959fd1d-675a-41e4-9f85-49b885d1bced.png align="center")

# 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.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">I created an idea in the APEX Ideas App suggesting that this functionality be included in APEX. You can see it <a target="_blank" rel="noopener noreferrer nofollow" href="https://apexapps.oracle.com/pls/apex/r/apex_pm/ideas/details?idea=FR-3367" style="pointer-events: none">here</a>.</div>
</div>
