Skip to main content

Command Palette

Search for a command to run...

Is There a Real Alternative to APEX_ITEM in Oracle APEX?

Updated
7 min read
Is There a Real Alternative to APEX_ITEM in Oracle APEX?
A

Oracle APEX inspired me into making a career change. Leveraging my experience with Project Management and Business Analysis and combining it with the most powerful low-code framework, I became a "Citizen Developer".

Introduction

This blog was inspired by a conversation with my dear colleague, Zoran Tica. While tackling a random technical challenge in Oracle APEX, we made the following assumption: there is no alternative for APEX_ITEM. I decided to investigate further to determine if this assumption holds true.

About APEX_ITEM

APEX_ITEM is a PL/SQL API that generates the HTML needed to add various types of input fields to your report regions. By looping through the returned records, you can process user input during page processing using custom PL/SQL code.

This API was widely used by developers to introduce interactivity into their reports or to support more dynamic, custom-built input forms. For example, the following region source:

SELECT
  apex_item.checkbox(1) sel,
  apex_item.hidden(2, empno) ||
  apex_item.text(3, ename, 'size=10') ename,
  job,
  apex_item.date_popup(4, rownum, hiredate, 'DD.MM.YYYY') hiredate,
  apex_item.text(5, sal, 'size=6') || ' €' sal,
  apex_item.select_list(
    p_idx         => 6,
    p_value       => deptno,
    p_list_values => 'ACCOUNTING;10,RESEARCH;20,SALES;30,OPERATIONS;40',
    p_show_null   => 'YES',
    p_null_text   => '-Select-',
    p_item_id     => 'f06_#ROWNUM#'
  ) department
FROM emp
ORDER BY empno;

would render like this:

and can be handled with the following PL/SQL process:

FOR i IN 1 .. apex_application.g_f01.count LOOP
  UPDATE emp
     SET ename    = apex_application.g_f03(i),
         hiredate = TO_DATE(apex_application.g_f04(i), 'DD.MM.YYYY'),
         sal      = apex_application.g_f05(i),
         deptno   = apex_application.g_f06(i)
   WHERE empno    = apex_application.g_f02(i);
END LOOP;

This API is marked as legacy

Many of us raised our eyebrows when the API was marked as legacy in the APEX 20.2 release.

APEX 20.2 API Documentation

This means the API can still be used, but it should not be used for new development. Existing applications will continue to work, as backward compatibility has always been a high priority for APEX. However, there are several reasons why you should consider replacing it:

  • It bypasses important security features, such as XSS protection and session state protection.

  • It sidesteps APEX’s validation and dynamic action framework.

  • Its output is not aligned with Universal Theme styling.

Given how commonly it was used, you might have expected a clearly documented alternative, right? But until now, there hasn’t been an officially defined replacement.

That still doesn’t mean no alternatives exist.

As my colleague Zoran likes to say on (too) many occasions: “It depends.” And indeed, it really does depend on the use case.

Use Case 1 - Multiline editing

APEX_ITEM was one of the building blocks of the now-desupported Tabular Forms. These forms were the predecessor of the Interactive Grid when it came to multiline editing. So if you need a report where users can edit multiple records directly, then in most cases you should either:

  • Use an Interactive Grid, which is the official successor to Tabular Forms, or

  • Abandon multiline editing for the region and use a modal form page on top of your Interactive or Classic Report. I often see developers force multi-line editing instead of single record editing without any real business case behind it. Single record editing can be handled a lot more easily and is often more user-friendly and convenient to the end user.

Use Case 2 - Dynamic forms

Some developers used APEX_ITEM to generate input fields dynamically based on context — for example, flexible forms driven by product category or metadata.

APEX still does not offer a native, declarative equivalent for fully dynamic input generation.

If you need this pattern, one option is a commercial plugin:
FlowForms by United Codes
https://www.united-codes.com/ords/r/pip/flowforms/2

Use Case 3: Row Selection in Reports

I could be wrong, but my assumption is that in most cases developers use APEX_ITEM to add checkboxes to their Classic and Interactive Reports so they can provide row selection capabilities. That has certainly been the case in many APEX applications I have encountered.

For this use case, Oracle APEX now offers several native alternatives. Let’s take a look at the built-in options and walk through each one.

Dropdown Page Items with Multiselect

I know that using page items for multi-selection isn’t the same as selecting rows in a report. However, I’ve seen many scenarios where a simple multiselect dropdown solved the requirements just as well. And with recent APEX versions, the available options are actually quite good. Three page item types can serve as alternatives to a multi-select report.

The Popup LOV, which was redesigned in APEX 19.2, continues to improve in later versions. It is still the only item type that supports multiple columns in the inline dialog. Selecting multiple values can feel a bit cumbersome because the user has to reopen the dialog after each selection.

The Combobox item, introduced in APEX 23.2, handles multiple selection much more conveniently. The user can select multiple records directly by clicking the checkboxes. If records were pre-selected when the page was rendered, those rows are already marked as selected. The display value can also be formatted using HTML expressions and template directives.

The Select-Many page item type, introduced in APEX 24.1, is very similar to the Combobox. I had to look quite closely to understand the differences. Select-Many does not allow the user to add new values that are not part of the LOV source query, while the Combobox does. On the other hand, Select-Many is a bit more user-friendly because it shows a badge with the total number of selected records, and clicking that badge filters the list to display only the selected items.

For all three page item types you can define how the multiple values are stored in the session state. They can be stored as comma-separated values (for example: APEX,SQL,PL/SQL), which you can process with the APEX_STRING API:

select column_value from apex_string.split ( :ITEM_NAME, ',' );

Or they can be stored in JSON format (for example: ["APEX", "SQL", "PL/SQL"]), which you can handle using the JSON_TABLE SQL function:

select
    element
from
    json_table ( :ITEM_NAME, '$[*]'
        columns
            element varchar2 path '$'
    );

Interactive grid - row selector

In APEX 24.1 it became easier to use the native row selector in the Interactive Grid to achieve multiselect functionality. You can define the page item where the selected values are stored by updating the Interactive Grid’s Initialization JavaScript Function in the Attributes tab:

function( config ) {
  config.defaultGridViewOptions = {
    selectionStateItem: "P3_SELECTED_IDS",
    multiple: true
  };
  return config;
}

Template components

Declarative row selection options were added to Template Components in APEX 24.1. From a user experience point of view, this is similar to the Combobox and Select-Many items, but it allows for more customization and flexibility.

To enable row selection, you first define which column in the report serves as the primary key. After that, you can turn on row selection in the Attributes tab.

The only thing I am missing in Template Components is the ability to define column headers. Because of that limitation, Template Components may not be a suitable alternative when you need a multi-column report where you previously used APEX_ITEM for row selection. Without column headers, it is difficult to achieve a simple, traditional tabular layout.

When Is It Hard to Say Goodbye to APEX_ITEM

As mentioned earlier, APEX_ITEM is still very useful when you need to build dynamically generated input forms, and this is an area where native APEX features cannot fully replace it.

The same applies to dynamic reports. Sometimes you need to squeeze an input field directly into a column’s output, or conditionally show a checkbox only for certain rows. These patterns are difficult to reproduce with purely declarative components. Here is a simple example:

Region source:

SELECT
    CASE
        WHEN job = 'SALESMAN' THEN
            APEX_ITEM.CHECKBOX(1)
        ELSE
            NULL
    END AS sel,
    APEX_ITEM.HIDDEN(2, empno)
    || APEX_ITEM.TEXT(3, ename) AS ename,
    job,
    APEX_ITEM.DATE_POPUP(4, ROWNUM, hiredate, 'DD.MM.YYYY') AS hiredate,
    CASE
        WHEN job = 'SALESMAN' THEN
            sal || ' € --> ' || APEX_ITEM.TEXT(5, NULL) || ' €'
        ELSE
            sal || ' €'
    END AS sal
FROM emp
ORDER BY empno;

Conclusion

While it will be difficult to remove APEX_ITEM for every use case, it has never been easier to achieve row selection declaratively in Oracle APEX. In the past this was often a cumbersome task, but today the platform offers several native ways to handle it without falling back to APEX_ITEM. For row selection use cases, these options are more than capable, and I see no reason to continue using APEX_ITEM for that purpose alone. In most scenarios there is already a suitable replacement in the APEX toolbox.

You should definitely evaluate the alternatives and replace APEX_ITEM wherever possible, rather than burden your future self with legacy components.

That said, I am sure it will take time before APEX_ITEM disappears from our applications entirely. And unless the APEX team introduces a direct, one-to-one equivalent, it will likely remain present in legacy code for quite a while.