How to Make an Item Read Only in Oracle APEX Without Losing Its Value

A short, step-by-step fix for disabled form items that save as empty or fail with a required error, with a readable read-only style.

A common requirement in Oracle APEX forms: when the user picks one option, another field must be locked. For example, an order form with a Delivery Method radio group, where the Delivery Address must not be changed when the method is Pickup.

The obvious solution is a dynamic action with the Disable action. It looks right on the screen, but when the user saves the form, the value of the disabled field is lost, or APEX shows an error such as "Delivery Address must have some value". This article shows why that happens and how to make the field read only instead, so the value is kept and still looks clear to the user.

The Problem with Disable

The demo form below has a dynamic action on the Delivery Method radio group: when the value is Pickup, it disables the Delivery Address item. Mary Johnson's order is a pickup, so the address is disabled and shown in a faded gray:

Order form with Delivery Method Pickup and a faded, disabled Delivery Address field
The Delivery Address is disabled by a dynamic action

The user changes only the notes and clicks Apply Changes. The save succeeds, but the address is gone:

Orders report where Mary Johnson's delivery address is now empty
After the save, Mary Johnson's address is empty

If the Delivery Address item is required, the save fails instead, although the address is visible on the screen:

Order form with the error Delivery Address must have some value
A required disabled item fails with "must have some value"

The reason is in HTML itself: the browser never sends a disabled field with the form. APEX receives no value for the item, so it treats the item as empty. The form process then writes NULL to the column, or a required check fails. The same happens when you disable an item in JavaScript with apex.item("P5_DELIVERY_ADDRESS").disable().

The Fix: Read Only Instead of Disabled

A read-only field also cannot be changed by the user, but the browser still sends its value with the form. So the form saves the value that was already there. APEX has no dynamic action for read only, but one line of JavaScript does it, and a few lines of CSS give the field a clear, readable look instead of the faded gray of a disabled item.

The steps below use the page "Order (Read Only)", page 5 of the demo application, with the items P5_DELIVERY_METHOD (a radio group with the values PICKUP and DELIVERY) and P5_DELIVERY_ADDRESS (a text field).

Step 1: Add the JavaScript Function and CSS to the Page

In Page Designer, click the page name at the top of the Rendering tree to show the page properties. In JavaScript, Function and Global Variable Declaration, enter:

// Makes an item read only (or editable again).
// Unlike disable, a read-only item is still submitted with the page.
function setItemReadOnly(itemName, readOnly) {
  $('#' + itemName).prop('readOnly', readOnly);
  $('#' + itemName + '_CONTAINER').toggleClass('is-readonly-item', readOnly);
}

The function setItemReadOnly takes two parameters:

  • itemName: the name of the page item, for example 'P5_DELIVERY_ADDRESS'.
  • readOnly: true to make the item read only, false to make it editable again.

With true, it sets the readOnly property of the item, so the user cannot type into it, and adds the class is-readonly-item to the item's container for the styling in the CSS below. With false, it removes both, and the item works as a normal field again. In both cases the item stays enabled, so its value is always submitted with the page. You can call it for any text field on the page, for example setItemReadOnly('P5_CUSTOMER_NAME', true).

Then, in CSS, Inline, enter:

.is-readonly-item .t-Form-inputContainer .apex-item-text {
  background-color: #f1f3f5;
  color: #1f2937;
  cursor: not-allowed;
}

This gives a read-only text field a light gray background with dark text, so it is clearly locked but still easy to read.

Page Designer with the page selected, the setItemReadOnly function in Function and Global Variable Declaration, and the CSS in Inline
The function and the CSS in the page properties

Step 2: Create the Dynamic Action

In the Rendering tree, right-click the radio group P5_DELIVERY_METHOD and choose Create Dynamic Action:

Context menu of P5_DELIVERY_METHOD in Page Designer with Create Dynamic Action highlighted
Create Dynamic Action on the radio group

Select the new dynamic action and set:

  • Identification, Name: Address only for delivery
  • When, Event: Change
  • When, Selection Type: Item(s), Item(s): P5_DELIVERY_METHOD
  • Client-side Condition, Type: Item = Value
  • Client-side Condition, Item: P5_DELIVERY_METHOD, Value: PICKUP
Dynamic action properties with Event Change, Item P5_DELIVERY_METHOD, and Client-side Condition Item = Value PICKUP
The dynamic action runs when the delivery method changes, and its condition is true for Pickup

With a client-side condition, the dynamic action has two branches: True actions run when the method is Pickup, False actions run for any other value.

Step 3: Add the True Action

Select the action under True and set:

  • Identification, Action: Execute JavaScript Code
  • Settings, Code: setItemReadOnly('P5_DELIVERY_ADDRESS', true);
  • Execution, Fire on Initialization: On
True action Execute JavaScript Code with setItemReadOnly P5_DELIVERY_ADDRESS true and Fire on Initialization on
The True action makes the address read only

Fire on Initialization runs the action when the page opens, so an order that is already a pickup opens with the address locked.

Step 4: Add the False Action

Right-click the True action and choose Create Opposite Action, or right-click False and create an action. Set:

  • Identification, Action: Execute JavaScript Code
  • Settings, Code: setItemReadOnly('P5_DELIVERY_ADDRESS', false);
  • Execution, Fire on Initialization: On
False action Execute JavaScript Code with setItemReadOnly P5_DELIVERY_ADDRESS false and Fire on Initialization on
The False action makes the address editable again

Click Save.

The Result

Open Mary Johnson's order again. The address is locked, with dark, readable text on a light gray background:

Order form with Delivery Method Pickup and a read-only Delivery Address with dark text on a light gray background
The read-only address is locked but easy to read

Typing into the address does nothing. Switching to Delivery makes it editable again, and switching back to Pickup locks it. Change the notes and click Apply Changes: this time the address is saved unchanged.

Orders report where Mary Johnson's address 15 Oak Street, Boston is kept and the notes are updated
After the save, the address is still there and the notes are updated

Good to Know

  • The readOnly property works for text fields, number fields, and textareas. For a textarea, add its class to the CSS selector: .is-readonly-item .t-Form-inputContainer .apex-item-textarea. Select lists, radio groups, checkboxes, and switches ignore readOnly, so they need a different approach.
  • Read only, like disabled, only works in the browser. A user who knows the browser's developer tools can still change the value. If the value must not change on the server either, add a validation or a process that checks it.
  • To use setItemReadOnly on several pages, move the function and the CSS from the page into application files, in Shared Components, Static Application Files, and reference them in the User Interface attributes of the application.
  • If you only need to show a value that the user never edits on this page, set the item's Read Only condition to Always in Page Designer instead. The form then keeps the value on save. That setting is decided when the page is rendered, so it cannot react to the user's clicks the way the dynamic action does.

Summary

Disabling a form item with a dynamic action or apex.item().disable() stops the browser from sending its value, so APEX saves NULL or reports a required-item error. Make the item read only instead: a small setItemReadOnly function, a few lines of CSS, and a dynamic action with an Execute JavaScript Code action for the True and False branches. The user cannot change the field, it stays readable, and the form saves its value correctly.

Vinish Kapoor
Vinish Kapoor

An Oracle ACE, author of four books on Oracle APEX, SQL and PL/SQL, and Oracle Forms, and a software developer building Oracle database applications since 2001.

guest

0 Comments
Oldest
Newest Most Voted
00