How to Get, Set, and Control Page Items Using apex.item in Oracle APEX

A complete guide to the Oracle APEX apex.item JavaScript API, with a tested example and real output for every method, plus three recipes for real forms.

Almost every piece of JavaScript you write in an Oracle APEX application touches a page item. You read what the user typed, fill in a value from somewhere else, hide a field that no longer applies, or check whether anything changed before the user leaves.

The apex.item API handles all of that through one consistent interface. A text field, a select list, a shuttle, a date picker, and a rich text editor all answer to the same methods, so you never need to know how each item type stores its value in the page. This guide covers every method of that interface, with a working example and its real output for each, plus three recipes you can drop into your own forms.

Quick Reference

Method or propertyWhat it does
getValue, setValue, valueRead and write the item's value
addValue, removeValueAdd or remove one value in a multi-value item
displayValueForTurn a stored value into the text the user sees
getMultiValueStorage, getSeparatorFind out how a multi-value item stores its values
isEmpty, hasDisplayValue, isChangedCheck whether the item has a value, shows something, or was edited
disable, enable, isDisabledLock and unlock the item for editing
hide, showHide or show the item together with its label
setFocus, setStyleMove the cursor into the item, or set one CSS property
getValidity, getValidationMessageRun client-side validation and get its message
refresh, isReady, whenReadyReload the item from the server, and wait for it to finish loading
getNativeValueNumber fields only: the value as a real JavaScript number
apex.item.isItem, create, addAttachHandlerTest whether an ID is an item, and build item plug-ins

How to Run These Examples

Every example below was run in Oracle APEX 26.1 on a test page that holds one item of every type, with names such as P20_TEXT, P20_NUMBER, and P20_SELECT_MANY. The output shown under each example is exactly what the browser console printed, not a reconstruction.

To try one yourself, open a page in your application, press F12 to open the developer tools, paste the code into the Console tab, and change the item names to ones on your page. For code you want to keep, put the same lines in a dynamic action with the Execute JavaScript Code action, or in the page's Execute when Page Loads attribute. If you are new to that side of APEX, the guide to JavaScript and CSS in Oracle APEX covers where code belongs.

The Item Interface and Its Properties

Calling apex.item with an item name returns that item's interface. It carries five properties, which are handy when you need to reach the underlying HTML or check what kind of item you are dealing with.

PropertyTypeDescription
idstring or falseThe ID of the item's main element, which for a page item is its name. False when the item is not on the page.
nodeElement or falseThe element that best represents the value. False when the item is not on the page.
elementjQueryThe item's element as a jQuery object, or an empty one when the item is not on the page.
item_typestringThe type of item, such as NUMBER or DATE_PICKER.
valuestring or ArrayA shortcut for getValue and setValue.
const date = apex.item("P20_DATE");
console.log("id:", date.id);
console.log("item_type:", date.item_type);
console.log("node:", date.node.tagName, date.node.id);
console.log("element:", date.element.length, "element(s)");

Output:

id: P20_DATE
item_type: DATE_PICKER
node: A-DATE-PICKER P20_DATE
element: 1 element(s)

Look at what the node of a date picker turns out to be: an a-date-picker element, not an input. That is exactly why you should read values through getValue rather than reaching into node.value yourself, because the markup behind an item type can change between releases while the interface stays the same.

value

Reading the value property calls getValue, and assigning to it calls setValue. It keeps simple code short, but reach for setValue when you need its extra parameters.

item.value → string | Array
item.value = pValue
const text = apex.item("P20_TEXT");
console.log(text.value);
text.value = "Glacier Trekking Poles";   // the same as setValue
console.log($v("P20_TEXT"));

Output:

Trailblazer 2-Person Tent
Glacier Trekking Poles

Reading and Setting Values

getValue

Returns the item's current value: a string, or an array of strings for items that hold several values, such as a shuttle, a checkbox group, or a select list with multiple selection.

item.getValue() → string | string[]
console.log(apex.item("P20_TEXT").getValue());
console.log(apex.item("P20_NUMBER").getValue(), typeof apex.item("P20_NUMBER").getValue());
console.log(apex.item("P20_SELECT_MANY").getValue());

Output:

Trailblazer 2-Person Tent
1,250.00 string
[]

Two results in that output catch people out. The number field returns formatted text, "1,250.00", rather than a number, and an empty multi-value item returns an empty array rather than an empty string. Both are covered further down.

Keep in mind where the value lives. The initial value comes from session state when the page renders, but anything the user or your code changes afterwards exists only in the browser until the page is submitted or the item is sent to the server in an Ajax call. The guide to session state in Oracle APEX explains why that distinction causes so many "my value didn't save" bugs.

setValue

Sets the item's value and fires its change event, so dynamic actions and any other listeners react exactly as if the user had changed it.

item.setValue(pValue, [pDisplayValue], [pSuppressChangeEvent])
ParameterTypeDescription
pValuestring or string[]The value, or an array of values for multi-value items.
pDisplayValuestringThe text to show, for items that cannot look it up themselves, such as a popup LOV that has not loaded its list.
pSuppressChangeEventbooleanPass true to set the value without firing the change event. Defaults to false.
apex.item("P20_TEXT").element.on("change", () => console.log("change event, new value:", $v("P20_TEXT")));

apex.item("P20_TEXT").setValue("Summit Down Sleeping Bag");
apex.item("P20_TEXT").setValue("Trail Runner Pack", null, true);   // no change event
console.log("value now:", $v("P20_TEXT"));

apex.item("P20_SELECT_MANY").setValue(["1", "3"]);                  // several values
console.log("select many:", apex.item("P20_SELECT_MANY").getValue());

Output:

change event, new value: Summit Down Sleeping Bag
value now: Trail Runner Pack
select many: ["1", "3"]

The handler printed a line for the first setValue call but not the second, because the second passed true as its third argument. Suppressing the event matters most when you set a value from inside a change handler, where letting it fire would trigger the handler again and start an endless loop.

The declarative equivalent is the Set Value dynamic action, and the Set Value dynamic action examples show when that is the simpler choice.

addValue

Adds one value to an item that holds several, such as a select many or a multi-value combobox. Item types that do not support multiple values simply ignore the call.

item.addValue(pValue, [pDisplayValue])
const many = apex.item("P20_SELECT_MANY");
many.setValue([]);
many.addValue("2");
many.addValue("4");
console.log(many.getValue());

Output:

["2", "4"]

removeValue

Removes one value from a multi-value item, leaving the rest in place.

item.removeValue([pValue])
const many = apex.item("P20_SELECT_MANY");
many.setValue(["1", "2", "4"]);
many.removeValue("2");
console.log(many.getValue());

Output:

["1", "4"]

displayValueFor

Returns the text the user would see for a given value: the label of a select list option, the text of a radio button, or the formatted version of a number. Pass an array to a multi-value item and you get the display values joined with commas.

item.displayValueFor(pValue, [pState]) → string
const department = apex.item("P20_DEPARTMENT");
const first = department.element.find("option[value!='']").first().val();
console.log(first, "is", department.displayValueFor(first));

const shuttle = apex.item("P20_SHUTTLE");
const values = shuttle.element.find("option").slice(0, 2).map((i, o) => o.value).get();
console.log(values, "are", shuttle.displayValueFor(values));

// Select Many loads its options when the user opens it: until then it has no display values
console.log(apex.item("P20_SELECT_MANY").displayValueFor(["1", "3"]));

Output:

1 is Camping
["11", "16"] are Backpacks, Base Layers
["1", "3"]

The last line is the one to understand. An item can only translate values it already knows, and a select many loads its options only when the user opens it, so before that it hands back the raw values unchanged. The optional pState parameter is for interactive grid column items, whose display can depend on whether the cell is read only.

getMultiValueStorage

Tells you how a multi-value item packs its values when the page is submitted: either separated by a character, or as a JSON array. This reflects the item's Multiple Values setting, and it returns null for single-value items.

item.getMultiValueStorage() → Object | null
console.log("select many:", apex.item("P20_SELECT_MANY").getMultiValueStorage());
console.log("shuttle:", apex.item("P20_SHUTTLE").getMultiValueStorage());
console.log("text field:", apex.item("P20_TEXT").getMultiValueStorage());

Output:

select many: {"type":"separated", "separator":":"}
shuttle: {"type":"separated", "separator":":"}
text field: null

getSeparator

Returns just the separator character of a multi-value item. It returns null for single-value items, and also for items that store their values as a JSON array.

item.getSeparator() → string | null
console.log("select many:", JSON.stringify(apex.item("P20_SELECT_MANY").getSeparator()));
console.log("checkbox group:", JSON.stringify(apex.item("P20_CHECKBOX_GROUP").getSeparator()));
console.log("text field:", apex.item("P20_TEXT").getSeparator());

Output:

select many: ":"
checkbox group: ":"
text field: null

This is the value to use when you split a submitted multi-value item on the server, rather than hard-coding a colon and hoping nobody changes the item's settings.

Checking the Item's State

isEmpty

Returns true when the item has no value. It is more forgiving than comparing against an empty string: a value made only of spaces, tabs, or line breaks counts as empty, and so does the null value of an item with a list of values.

item.isEmpty() → boolean
console.log(apex.item("P20_TEXT").isEmpty());
apex.item("P20_TEXT").setValue("   ");
console.log(apex.item("P20_TEXT").isEmpty());         // only spaces count as empty
console.log(apex.item("P20_PASSWORD").isEmpty());

Output:

false
true
true

hasDisplayValue

Returns true when the item shows anything at all, whether a value or a placeholder. It answers a question about the display rather than the data, which is what you need when deciding, for example, whether a floating label should move out of the way.

item.hasDisplayValue() → boolean
const text = apex.item("P20_TEXT");
console.log("text shows a value:", text.hasDisplayValue());
text.setValue("");
console.log("after clearing:", text.hasDisplayValue(), "- empty:", text.isEmpty());

Output:

text shows a value: true
after clearing: false - empty: true

isChanged

Returns true when the value differs from what it was when the page loaded. APEX relies on this to warn users about unsaved changes, and apex.page.isChanged asks the same question of every item on the page at once.

item.isChanged() → boolean
const text = apex.item("P20_TEXT");
console.log(text.isChanged());
text.setValue("Trail Runner Pack");
console.log(text.isChanged());
console.log("page changed:", apex.page.isChanged());

Output:

false
true
page changed: true

For a different angle on the same problem, see how to check whether an item value changed using a dynamic action.

Showing, Hiding, and Locking Items

disable and enable

Disable makes an item unavailable for editing, and enable makes it editable again.

item.disable()
item.enable()
const text = apex.item("P20_TEXT");
text.disable();
console.log("disabled:", text.isDisabled());
text.enable();
console.log("disabled:", text.isDisabled());

Output:

disabled: true
disabled: false
const radio = apex.item("P20_RADIO");
radio.disable();
radio.enable();
console.log("P20_RADIO disabled:", radio.isDisabled());

Output:

P20_RADIO disabled: false

There is one consequence to plan for. A disabled item is not submitted with the page, so if its value still needs saving, make the item read only on the server instead of disabling it in the browser.

isDisabled

Returns true when the item is currently disabled.

item.isDisabled() → boolean
console.log(apex.item("P20_DISPLAY_ONLY").isDisabled());
apex.item("P20_NUMBER").disable();
console.log(apex.item("P20_NUMBER").isDisabled());

Output:

false
true

Note the first line: a Display Only item reports false. It is not disabled, it is simply not editable, which is a different thing and matters when your code tests one to infer the other.

hide and show

Hide and show the item along with its label, whatever the page layout. The Show and Hide dynamic actions call these same two methods.

item.hide()
item.show()
apex.item("P20_NUMBER").hide();
apex.item("P20_DATE").hide();
console.log("number visible:", apex.jQuery("#P20_NUMBER_CONTAINER").is(":visible"));

Output:

number visible: false
A region of text items in Oracle APEX after hiding the number field and date picker with apex.item hide
The Text Items region after hiding the number field and the date picker.
const number = apex.item("P20_NUMBER");
number.hide();
number.show();
console.log("number visible:", apex.jQuery("#P20_NUMBER_CONTAINER").is(":visible"));

Output:

number visible: true

Older code sometimes passes a parameter to hide or show that hid a whole table row in legacy themes. That parameter is deprecated, and modern themes do not need it.

setFocus

Moves the keyboard focus into the item, specifically into the part designed to receive it, such as the input of a popup LOV rather than its button.

item.setFocus()
apex.item("P20_NUMBER").setFocus();
console.log("focus is on:", document.activeElement.id);

Output:

focus is on: P20_NUMBER

setStyle

Sets a single CSS property on the element meant to receive styles.

item.setStyle(pPropertyName, pPropertyValue)
apex.item("P20_TEXT").setStyle("backgroundColor", "#fff3cd");
console.log($x("P20_TEXT").style.backgroundColor);

Output:

rgb(255, 243, 205)
An Oracle APEX text field with a yellow background set using apex.item setStyle
The text field with its background set through setStyle.

Use it sparingly. Adding and removing CSS classes keeps styling in your stylesheet, where the theme and dark mode can adjust it, whereas an inline style set from JavaScript overrides both.

Validating Items in the Browser

getValidity

Returns the item's ValidityState, the standard HTML constraint validation object, with flags such as valid, valueMissing, typeMismatch, and rangeOverflow. APEX calls it for every item when a page is submitted with client-side validation switched on.

item.getValidity() → ValidityState
const text = apex.item("P20_TEXT");
text.node.required = true;
text.setValue("");
const validity = text.getValidity();
console.log("valid:", validity.valid, "- valueMissing:", validity.valueMissing);

Output:

valid: false - valueMissing: true

getValidationMessage

Returns the message APEX would show for an invalid item, or an empty string when the item is valid. To replace the default wording, put your own text in the item's data-valid-message attribute.

item.getValidationMessage([pLabel]) → string
const text = apex.item("P20_TEXT");
text.node.required = true;
text.setValue("");
console.log(text.getValidationMessage());

// a message of your own, in the attribute that APEX reads
text.element.attr("data-valid-message", "Enter the product name, for example Trail Runner Pack.");
console.log(text.getValidationMessage());

Output:

Text Field must have some value.
Enter the product name, for example Trail Runner Pack.

Client-side checks save a round trip, but they never replace server-side validations, because anything in the browser can be bypassed.

Refreshing Items and Waiting Until They Are Ready

refresh

Reloads the item from the server. For a select list, radio group, or checkbox group based on a SQL list of values, that means fetching the list again, which is what APEX itself does to a cascading list when its parent changes. The item fires apexbeforerefresh and apexafterrefresh around the reload.

item.refresh()
const category = apex.item("P20_CATEGORY");
category.element.on("apexafterrefresh", () =>
    console.log("categories after refresh:", category.element.find("option").length));
apex.jQuery("#P20_DEPARTMENT").val(apex.jQuery("#P20_DEPARTMENT option[value!='']").eq(1).val());
category.refresh();

Output:

categories after refresh: 3

Notice the example listens for apexafterrefresh rather than reading the options straight after calling refresh. The reload is asynchronous, so reading immediately would give you the old list.

isReady

Returns true once the item has finished loading. Most items are ready instantly, but items built on libraries that load asynchronously, such as the rich text editor, may not be when your page-load code starts.

item.isReady() → boolean
const editor = apex.item("P20_RICH_TEXT");
console.log("rich text editor ready:", editor.isReady());
console.log("text field ready:", apex.item("P20_TEXT").isReady());

Output:

rich text editor ready: true
text field ready: true

whenReady

Returns a promise that resolves when the item is ready. It is the safe way to set the value of a rich text editor from page-load code, where calling setValue too early silently does nothing.

item.whenReady() → Promise
const editor = apex.item("P20_RICH_TEXT");
await editor.whenReady();                        // the editor library has loaded
editor.setValue("<p>Ships in <strong>2 days</strong>.</p>");
console.log(editor.getValue());

Output:

<p>Ships in <strong>2 days</strong>.</p>

Working with Number Fields

A number field has the full item interface, plus behavior that understands numbers and its format mask. Its item_type is NUMBER, and the methods it inherits unchanged, such as disable and hide, work exactly as described above. The examples use a field with the format mask 999G999G990D00.

getValue

Returns the value exactly as the field shows it, formatted by the mask, and always as a string.

numberField.getValue() → string
const number = apex.item("P20_NUMBER");
console.log(JSON.stringify(number.getValue()));   // as formatted in the field
console.log(number.getNativeValue());

Output:

"1,250.00"
1250

getNativeValue

Returns the value as a JavaScript number you can calculate with. This is the method to use whenever arithmetic is involved.

numberField.getNativeValue() → number
const number = apex.item("P20_NUMBER");
console.log(number.getValue(), typeof number.getValue());
console.log(number.getNativeValue(), typeof number.getNativeValue());
number.setValue("abc");
console.log(number.getNativeValue());

Output:

1,250.00 string
1250 number
null

Watch the last line. Oracle's documentation says a value that is not a number returns NaN, but in APEX 26.1 it actually returns null. Test for both with value === null || isNaN(value) and your code will survive either behavior.

setValue

Accepts a JavaScript number as well as a string, and formats it with the field's mask.

numberField.setValue(pValue, [pDisplayValue], [pSuppressChangeEvent])
const number = apex.item("P20_NUMBER");
number.setValue(1999.5);                  // a JavaScript number is accepted
console.log(number.getValue());
number.setValue("2500");
console.log(number.getValue(), "->", number.getNativeValue() + 1);

Output:

1,999.50
2,500.00 -> 2501

displayValueFor

Formats any value with the field's mask, without changing the field itself.

numberField.displayValueFor(pValue) → string
const number = apex.item("P20_NUMBER");      // format mask 999G999G990D00
console.log(number.displayValueFor("1250"));
console.log(number.displayValueFor("1234567.5"));

Output:

1,250.00
1,234,567.50

isChanged

Compares numbers rather than text, so setting the same number in a different form, such as 1250 for 1,250.00, does not count as a change.

numberField.isChanged() → boolean
const number = apex.item("P20_NUMBER");
console.log(number.getValue(), number.isChanged());
number.setValue("1250");                  // the same number, unformatted
console.log(number.getValue(), number.isChanged());
number.setValue("1300");
console.log(number.getValue(), number.isChanged());

Output:

1,250.00 false
1,250.00 false
1,300.00 true

That numeric comparison is what keeps the unsaved-changes warning from firing just because a user retyped the same amount without the thousands separator.

The apex.item Namespace Functions

apex.item.isItem

Returns true when an element with the given ID exists and has an item interface. It returns false for missing IDs and for things that exist but are not items, such as regions.

apex.item.isItem(pItemId) → boolean
console.log(apex.item.isItem("P20_TEXT"));
console.log(apex.item.isItem("P20_NO_SUCH_ITEM"));
console.log(apex.item.isItem("text_items"));   // a region, not an item

Output:

true
false
false

apex.item.create

Creates the item interface for an item plug-in. The plug-in's JavaScript calls it once per item, passing only the functions that differ from the default behavior, and from then on apex.item, dynamic actions, and page submission all treat the plug-in like a built-in item.

apex.item.create(pItemId, pItemImpl) → Deferred | undefined
Property of pItemImplDescription
item_typeThe type name that item_type returns.
getValue, setValueHow to read and write the value. Without them, the defaults work for standard form elements.
displayValueForThe display text for a value.
isChangedWhether the value changed since the page loaded.
enable, disable, isDisabledHow to enable, disable, and test compound items.
show, hideHow to show and hide compound items.
setFocusTo, setStyleToThe element that receives focus, or styles.
getValidity, getValidationMessageValidation, for items that validate themselves.
refreshHow to refresh the item.
addValue, removeValue, storageType, separatorSupport for multiple values.
delayLoadingTrue when the item loads asynchronously. create then returns a jQuery Deferred that the plug-in resolves when ready.

Here is a minimal star-rating item kept in a plain span, supplying its own getValue, setValue, and isChanged:

// A minimal item plug-in: a span that holds a rating from 1 to 5
apex.jQuery("#text_items .t-Region-body").append('<span id="P20_STARS" class="stars">3</span>');

apex.item.create("P20_STARS", {
    item_type: "STARS",
    getValue: function () {
        return this.element.text();
    },
    setValue: function (value) {
        this.element.text(value);
    },
    isChanged: function () {
        return this.element.text() !== "3";
    }
});

const stars = apex.item("P20_STARS");
console.log(stars.item_type, "value:", stars.getValue(), "changed:", stars.isChanged());
stars.setValue("5");
console.log("value:", $v("P20_STARS"), "changed:", stars.isChanged());

Output:

STARS value: 3 changed: false
value: 5 changed: true

Once created, the span answers to apex.item and even to the $v shorthand, exactly like a built-in item. If you are building a plug-in, the guide to building your first Oracle APEX plug-in covers the surrounding setup.

apex.item.addAttachHandler

Registers a function that APEX calls while the page initializes, passing the context in which items are being created: the whole page, or a region that is being rendered again. An item plug-in uses it to initialize all its items in one place instead of rendering a separate JavaScript call for each one.

apex.item.addAttachHandler(pHandler)
apex.item.addAttachHandler(function (context$) {
    const count = context$.find(".apex-item-text").length;
    console.log("attach handler called with", context$.length, "context;", count, "text items in it");
});

Output:

attach handler called with 1 context; 11 text items in it

Timing is everything here. The handler must be registered before the page initializes, so it belongs in a JavaScript file that the plug-in loads, not in code that runs after the page is ready. Pasting it into the console after load, for example, does nothing.

Recipes

These three recipes solve tasks that come up on almost every form. Each block of code is labeled with where it goes in your application. Blocks labeled Try it simulate what a user would do, such as opening an order or clicking a button, so the recipe can demonstrate itself; you leave those out of your own application.

Require an Item Only in Some Cases

A shipped order needs a shipped date, but other orders do not, so the item cannot simply be marked Value Required. The solution listens for apexbeforepagesubmit, checks the two items only when the request is SAVE, shows the error beside the item, and cancels the submit.

The code goes in the page's Execute when Page Loads attribute. A dynamic action on the Before Page Submit event with an Execute JavaScript Code action works the same way.

// === Try it: open an order from the Orders page ===
$("#orders a[href*='order']").first()[0].click();
// --- on the Order page ---
// === Page › Execute when Page Loads ===
apex.gPageContext$.on("apexbeforepagesubmit", function(event, request) {
    if (request !== "SAVE") return;
    apex.message.clearErrors();
    if (apex.item("P10_STATUS").getValue() === "SHIPPED" && apex.item("P10_SHIPPED_DATE").isEmpty()) {
        apex.message.showErrors([{
            type: "error",
            location: ["inline", "page"],
            pageItem: "P10_SHIPPED_DATE",
            message: "Enter the date the order was shipped.",
            unsafe: false
        }]);
        apex.event.gCancelFlag = true;                          // the page is not submitted
    }
});
// === Try it: set the status to Shipped, leave Shipped Date empty, and click Apply Changes ===
apex.item("P10_STATUS").setValue("SHIPPED");
apex.item("P10_SHIPPED_DATE").setValue("");
$("button").filter((i, b) => b.textContent.trim() === "Apply Changes").trigger("click");
await new Promise((resolve) => setTimeout(resolve, 800));
console.log("submitted:", apex.page.isChanged() ? "no, the changes are still on the page" : "yes");
console.log("inline error:", $("#P10_SHIPPED_DATE_error").text());

Output:

submitted: no, the changes are still on the page
inline error: Enter the date the order was shipped.
An Oracle APEX form showing an inline error under the Shipped On date when the order is shipped
The inline error stops the submit until a shipped date is entered.

The error display comes from apex.message.showErrors, which the guide to displaying error messages with JavaScript explores further. Put the same rule in a server-side validation too: the browser check spares the user a round trip, but only the server can be trusted.

Set Cascading Lists from Code

Setting a department, a category, and a product one after another looks like it should work, and it does not. Each child list reloads its options from the server when its parent changes, so a value you set in the meantime is thrown away, and all three end up as 1, empty, and empty.

The fix is to wait for each child's apexafterrefresh event before setting it. The function goes in the page's Function and Global Variable Declaration, and the call goes wherever the values come from: a button, a search result, or saved preferences.

// === Page › Function and Global Variable Declaration ===
// Sets cascading lists in order: [[parent, value], [child, value], ...]
async function setCascading(values) {
    for (let i = 0; i < values.length; i++) {
        const [name, value] = values[i];
        const child = values[i + 1];
        // the child list reloads when its parent changes: wait for that before setting it
        const reloaded = child
            ? new Promise((resolve) => $("#" + child[0]).one("apexafterrefresh", resolve))
            : null;
        apex.item(name).setValue(value);
        await reloaded;
    }
}
// === Try it: choose a product in all three lists at once ===
await setCascading([["P20_DEPARTMENT", "1"], ["P20_CATEGORY", "9"], ["P20_PRODUCT", "16"]]);
for (const name of ["P20_DEPARTMENT", "P20_CATEGORY", "P20_PRODUCT"]) {
    const value = apex.item(name).getValue();
    console.log(name, value, apex.item(name).displayValueFor(value));
}

Output:

P20_DEPARTMENT 1 Camping
P20_CATEGORY 9 Camp Kitchen
P20_PRODUCT 16 Blaze Two-Burner Stove

This is the same cascading behavior described in the guide to page items and lists of values, seen from the JavaScript side.

Lock a Form When Its Record Is Closed

Once an order is delivered, only its status should be editable. The function disables every item in the form except the status, hides the Apply Changes button, whose HTML DOM ID is save_order, and switches off editing in the order lines grid through its edit action.

The function goes in the page's Function and Global Variable Declaration. Call it from Execute when Page Loads, and again from a dynamic action on the Change event of the status item.

// === Try it: open an order from the Orders page ===
$("#orders a[href*='order']").first()[0].click();
// --- on the Order page ---
// === Page › Function and Global Variable Declaration ===
// A shipped, delivered, or cancelled order can no longer be edited; only its status can change.
function lockOrder() {
    const locked = ["SHIPPED", "DELIVERED", "CANCELLED"].includes(apex.item("P10_STATUS").getValue());
    $("#order_form [id]").each((i, element) => {
        const name = element.id;
        if (/^P10_/.test(name) && name !== "P10_STATUS" && apex.item.isItem(name)) {
            if (locked) apex.item(name).disable(); else apex.item(name).enable();
        }
    });
    $("#save_order").toggle(!locked);                         // the Apply Changes button
    const grid = apex.region("order_lines").call("getActions");
    if (locked) { grid.set("edit", false); grid.disable("edit"); } else grid.enable("edit");
}
// === Page › Execute when Page Loads, and a dynamic action on Change of P10_STATUS ===
lockOrder();
// === Try it: set the status to Delivered ===
apex.item("P10_STATUS").setValue("DELIVERED");
lockOrder();
console.log("disabled:", ["P10_ORDER_DATE", "P10_CUSTOMER_ID", "P10_DISCOUNT_PCT", "P10_NOTES"]
    .filter((name) => apex.item(name).isDisabled()).join(", "));
console.log("Apply Changes visible:", $("#save_order").is(":visible"),
            "- grid editable:", !apex.region("order_lines").call("getActions").lookup("edit").disabled);

Output:

disabled: P10_ORDER_DATE, P10_CUSTOMER_ID, P10_DISCOUNT_PCT, P10_NOTES
Apply Changes visible: false - grid editable: false
An Oracle APEX order form with every field disabled except the status once the order is delivered
A delivered order: every field but Status is locked, and Apply Changes is gone.

Hiding the button is not a side effect but a necessity. Disabled items are not submitted, so leaving the button in place would let a user save a form with half its values missing. On the server, a read-only condition or an authorization scheme on the items stops a crafted request from changing a closed order, and the interactive grid guide covers the grid actions used here.

Conclusion

The apex.item interface gives every page item the same set of methods, which is what makes APEX JavaScript portable across item types. Use getValue and setValue to read and write values, remembering that setValue fires the change event unless you suppress it, and that neither touches session state until the page is submitted or the item is sent to the server. Multi-value items add addValue and removeValue, while displayValueFor, isEmpty, hasDisplayValue, and isChanged tell you what the item holds and whether it was edited. Show, hide, enable, disable, setFocus, and setStyle control presentation, with the caveat that disabled items are never submitted. Validation runs through getValidity and getValidationMessage, and refresh, isReady, and whenReady handle items that load asynchronously. Number fields add getNativeValue for arithmetic and compare numbers rather than text, and the apex.item namespace functions let your own plug-ins join the same interface.

Vinish Kapoor
Vinish Kapoor

An Oracle ACE and software veteran with 25+ years of experience, passionate about AI and IT innovation.

guest

0 Comments
Oldest
Newest Most Voted
00