Dynamic Column Labels in Oracle APEX Interactive Grid Using Page Items
When building data-driven applications in Oracle APEX, column headers sometimes need to reflect dynamic labels rather than hardcoded ones. This post walks through generating column names from a page item value.
The Requirement
The goal was straightforward: an Interactive Grid whose column headers are generated dynamically based on a page item, updating both on page load and whenever the user changes the item value manually.
The page item P24_LABEL_ITEM holds a range string in this format:
RESULT1-RESULT5
This means the grid columns should be labeled RESULT1,RESULT2, RESULT3 ... RESULT5 sequentially — without any hardcoding in the region or column settings.
The JavaScript Solution
Place the following code under Execute when Page Loads. The same block can be reused inside a Dynamic Action triggered on the page item's Change event.
setTimeout(function () {
let itemValue = $v("P24_LABEL_ITEM");
let labels = [];
if (itemValue) {
// Parse prefix and numeric range from "RESULT1-RESULT5"
let parts = itemValue.split("-");
let prefix = parts[0].match(/[A-Za-z]+/)[0];
let start = parseInt(parts[0].replace(/\D/g, ""));
let end = parseInt(parts[1].replace(/\D/g, ""));
// Build label array: ["RESULT1", "RESULT2", ..., "RESULT5"]
for (let i = start; i <= end; i++) {
labels.push(prefix + i);
}
// Access the Interactive Grid region
let region = apex.region("IG_ST_ID");
let ig$ = region.widget();
let view = ig$.interactiveGrid("getCurrentView");
// Detect edit mode via the model's editable option
let isEditMode = view && view.model && view.model.getOption("editable");
// In edit mode, skip first 2 system columns (checkbox + row actions)
let skipCount = isEditMode ? 2 : 0;
let labelIndex = 0;
let currentIndex = 0;
let $headers = $("#IG_ST_ID").find(".a-GV-header, .a-GV-columnHeader");
$headers.each(function () {
let $th = $(this);
if (currentIndex < skipCount) {
currentIndex++;
return;
}
let $label = $th.find(".a-GV-headerLabel");
if ($label.length && labelIndex < labels.length) {
$label.text(labels[labelIndex]);
labelIndex++;
}
currentIndex++;
});
}
}, 800);
The Key Challenge — Edit Mode Column Offset
Oracle APEX Interactive Grid renders extra system columns when the grid is in Edit Mode that simply do not exist in read-only mode.
| Column Position | Edit Mode | Read-Only Mode |
|---|---|---|
| Column 1 | Row Selector (checkbox) | First data column |
| Column 2 | Row Actions (menu) | Second data column |
| Column 3 onward | Your data columns | — |
Without accounting for this offset, labels get applied to the system columns first — the first label lands on the checkbox column, the second on the row actions column, and all subsequent labels shift by two positions.
The Fix
Detect edit mode using the grid model's editable option and skip system columns accordingly:
let isEditMode = view && view.model && view.model.getOption("editable");
let skipCount = isEditMode ? 2 : 0;
During the header loop, a separate counter tracks position and skips the first skipCount elements before applying any labels — keeping the logic clean and working correctly regardless of grid mode.
Triggering on Page Item Change
To refresh labels when the user manually changes the item value, create a Dynamic Action with these settings:
True Action: Execute JavaScript Code — paste the same block above.
This ensures column headers remain in sync with the page item at all times, whether set by the application on load or changed by the user at runtime.
Result
- Page Load Labels generated from the page item after an 800ms render delay
- Edit Mode First 2 system columns correctly detected and skipped
- Item Change Dynamic Action re-runs the script and refreshes all headers
Why the 800ms Delay?
The setTimeout delay is intentional. APEX Interactive Grid takes time to fully render its DOM — including header elements — after the page finishes loading. Attempting to query .a-GV-headerLabel too early returns empty results. A delay of 800ms reliably covers the grid's internal initialization in most environments, though it can be tuned based on page complexity and network conditions.
The solution is clean, reusable, and works seamlessly across both grid modes without any changes to APEX column configuration.
Comments
Post a Comment