When building applications in Oracle APEX, form usability matters just as much as functionality. One common requirement is allowing users to type a plain 10-digit number into a field and having it automatically format into the standard US phone number format — (XXX) XXX-XXXX — as soon as they click or tab away from the field. This lose focus behavior, known as the blur event, gives users instant visual feedback that their input has been recognized and formatted correctly. This article walks you through how to achieve this in Oracle APEX using a Dynamic Action with a small piece of JavaScript.

Setting Up the Page Item
Start by creating a text field item on your APEX page — for example, P1_PHONE_NUMBER. Set the item type to Text Field rather than Number, because the formatted output will contain parentheses, a space, and a hyphen, which are non-numeric characters. If you use a Number type, APEX will reject these characters. You can optionally set the Maximum Length to 14 to match the length of the formatted output including the special characters, or leave it at 10 if you plan to store only the raw digits and format purely for display.
Creating a Dynamic Action on Lose Focus
Navigate to the Dynamic Actions tab in the Page Designer. Right-click on the P1_PHONE_NUMBER item and select Create Dynamic Action. Name it something descriptive like "Format as US Phone Number." Set the Event to Lose Focus, which fires whenever the user clicks outside the field or tabs to the next item. The Selection Type should be Item(s) and the Item(s) field should reference P1_PHONE_NUMBER.
Under the True action, choose Execute JavaScript Code as the action type. In the code editor, enter the following JavaScript:
var field = apex.item("P1_PHONE_NUMBER");
var value = field.getValue().replace(/\D/g, "");
if (value.length === 10) {
var formatted = "(" + value.substring(0, 3) + ") " + value.substring(3, 6) + "-" + value.substring(6);
field.setValue(formatted);
}
This script first retrieves the current value of the field and strips out any non-digit characters using the regular expression \D. This ensures that even if the user has already partially formatted the number or included dashes or spaces, the script works from a clean 10-digit string. It then checks that exactly 10 digits are present — the expected length of a US phone number without the country code. If the condition is met, it reconstructs the value in (XXX) XXX-XXXX format and sets it back into the field.
Handling Edge Cases and Validation
The script above only formats the number when it contains exactly 10 digits, which prevents partial or incorrect inputs from being mangled into a broken format. However, you may want to go further and alert the user when their input is invalid. You can extend the JavaScript to display a brief message or highlight the field:
var field = apex.item("P1_PHONE_NUMBER");
var value = field.getValue().replace(/\D/g, "");
if (value.length === 10) {
var formatted = "(" + value.substring(0, 3) + ") " + value.substring(3, 6) + "-" + value.substring(6);
field.setValue(formatted);
$("#P1_PHONE_NUMBER").css("border-color", "");
} else if (value.length > 0) {
$("#P1_PHONE_NUMBER").css("border-color", "red");
}
This version adds a red border to the field when the input has some digits but not exactly 10, giving the user a visual cue that their entry is incomplete or incorrect. The border resets to its default when a valid 10-digit number is entered and formatted. For a more polished user experience, you could also use the APEX apex.message.showErrors API to display a proper inline error message beneath the field.
Using Custom Attributes with Inline onblur
This is the quickest and most straightforward method. In the Page Designer, select your P1_PHONE_NUMBER item and navigate to the Advanced section in the Property Editor. In the Custom Attributes field, enter the following:
onblur="var v=this.value.replace(/\D/g,''); if(v.length===10){this.value='('+v.substring(0,3)+') '+v.substring(3,6)+'-'+v.substring(6);}"
This places an inline onblur event handler directly on the HTML input element. When the user leaves the field, the browser fires the blur event, which runs this JavaScript. The code strips all non-digit characters, checks for exactly 10 digits, and reformats the value as (XXX) XXX-XXXX. No Dynamic Action or separate JavaScript function is needed.
Storing Only Raw Digits in the Database
A best practice when storing phone numbers is to save only the raw digits in the database and apply formatting purely at the display level. This makes querying, comparing, and validating phone numbers much simpler. To achieve this, you can create a Before Submit computation or process that strips the formatting before the value is saved. Create a computation on P1_PHONE_NUMBER with the type PL/SQL Expression and use:
REGEXP_REPLACE(:P1_PHONE_NUMBER, '[^0-9]', '')
This removes all non-numeric characters before the value is inserted or updated in the database. When the page loads for editing, you can reapply the formatting using a similar Dynamic Action on the Page Load event, or by using a Post-Calculation Computation or Format Mask depending on your display requirements.
Alternative Approach Using an Input Mask Plugin
Oracle APEX also supports input mask functionality through community plugins or the built-in Format Mask property available in newer versions. If you prefer a guided input experience where the formatting appears as the user types rather than on lose focus, you can explore the popular Input Mask plugin available on apex.world. This plugin lets you define a mask like (999) 999-9999, and the field automatically enforces the pattern during input. However, the lose focus approach described above is often preferred because it feels less restrictive — users can type the digits naturally and see the formatting applied afterward.
Summary
Formatting a number field as a US phone number on lose focus in Oracle APEX requires just a text field item, a Dynamic Action triggered on the blur event, and a few lines of JavaScript. The script strips non-digit characters, validates the length, and reconstructs the value in (XXX) XXX-XXXX format. By combining this with server-side stripping before database storage, you get a clean user experience on the front end and consistent raw data on the back end. This approach works across all modern APEX versions and requires no plugins or external libraries.



