Dynamically Highlighting Required Fields in Oracle APEX

Have you ever wanted to highlight the background of required fields in your Oracle APEX application?

That’s easy, and it can improve the user experience.

I’ll show three approaches to changing the background colour of those fields dynamically.

Important notice

  • this solution works well with items: “Select list”, “Text field”, “Popup LOV” - it may work with others after minor tweaks, but I haven’t tested it

  • items must have this attribute set: Appearance → Template → Required-Floating

    ( it’s important if you want page-wide or app-wide implementation)

Prerequisites

Before diving in, ensure you have:

  1. CSS for Empty Fields

    Add the following CSS class to your page:

.empty-field {
    background-color: #FDE6E6 !important; 
    /* Light red background for empty fields */
}

The Goal: Highlight Empty Required Fields

Our goal is simple:

  1. Highlight empty fields with the chosen background colour.

  2. Remove the highlight when the field is filled.

Solution 1: Individual Dynamic Actions for Full Control

In this approach, you define Dynamic Actions for specific items. Each action checks if the field is empty and applies or removes the .empty-field class accordingly.

Step-by-Step Implementation

  1. Create a Dynamic Action for Each Field:
    For each field, create a Dynamic Action triggered On Change.

  2. Server-Side Condition:
    Use the function apex.item( "P1_ITEM" ).isEmpty() in the condition to determine if the field is empty.

     apex.item('P3_PROJECT_LEAD').isEmpty()
    
  3. Action Logic:

    • If empty, add the class .empty-field.

  • If filled, remove the class.

Solution 2: Generalized JavaScript Function for All Required Items at one page

If you prefer a more scalable approach, define a single Dynamic Action that calls a JavaScript function to handle all required fields on the page.

JavaScript Function: f_set_required_items_background

This function iterates through all required items and applies/removes the .empty-field CSS class as needed. Define it at the page level:

// Function to set background color for required items based on their value
function f_set_required_items_background() {
    // For each element on the page with classes 't-Form-fieldContainer' and 'is-required'
    document.querySelectorAll('.t-Form-fieldContainer.is-required').forEach(function(container) {
        // Look for the first visible input or select inside the div with the class 't-Form-itemWrapper'
        const inputWrapper = container.querySelector('.t-Form-itemWrapper input:not([type="hidden"]), .t-Form-itemWrapper select');
        // If an input or select is found
        if (inputWrapper) {
            const itemName = inputWrapper.id; // Get the item name from the input's or select's id (e.g., P3_PROJECT_LEAD)
            /
            const isEmpty = apex.item(itemName).isEmpty();

            // If the item value is empty (true), add the red background class
            if (isEmpty) {
                inputWrapper.classList.add('empty-field');
            } else {
                // If the item value is not empty (false), remove the red background class (if it exists)
                inputWrapper.classList.remove('empty-field');
            }
        }
    });
}

Triggering the Function

Define a Dynamic Action:

  1. Event: Change

  2. Selection Type: jQuery Selector

     .t-Form-fieldContainer.is-required .t-Form-itemWrapper :input
    

  3. Action: Execute JavaScript Code

     f_set_required_items_background();
    

Solution 3: Global implementation at Page 0

You can also apply this solution globally for your application by implementing on page 0. To do this, you need to:

  1. Create CSS and JS files in Static Application Files:

.empty-field {
    background-color: #FDE6E6 !important; /* Light red background for empty fields */
}
// Function to set background color for required items based on their value
function f_set_required_items_background() {
    // For each element on the page with classes 't-Form-fieldContainer' and 'is-required'
    document.querySelectorAll('.t-Form-fieldContainer.is-required').forEach(function(container) {
        // Look for the first visible input or select inside the div with the class 't-Form-itemWrapper'
        const inputWrapper = container.querySelector('.t-Form-itemWrapper input:not([type="hidden"]), .t-Form-itemWrapper select');
        // If an input or select is found
        if (inputWrapper) {
            const itemName = inputWrapper.id; // Get the item name from the input's or select's id (e.g., P3_PROJECT_LEAD)

            const isEmpty = apex.item(itemName).isEmpty();

            // If the item value is empty (true), add the red background class
            if (isEmpty) {
                inputWrapper.classList.add('empty-field');
            } else {
                // If the item value is not empty (false), remove the red background class (if it exists)
                inputWrapper.classList.remove('empty-field');
            }
        }
    });
}
  1. Point to those files in the User Interface Attributes of your application

  1. Implement Dynamic Action on Page 0

.t-Form-fieldContainer.is-required .t-Form-itemWrapper :input

f_set_required_items_background();

Now it works for all pages in your application :)

Conclusion

Both approaches work effectively depending on your needs:

  • Use Solution 1 for granular control over individual fields.

  • Use Solution 2 for quick, page-wide implementation.

  • Use Solution 3 for app-wide implementaion

One more thing: I’m not a super Java Script guy. If you know a better (simpler!) solution, please comment.

Happy coding! 🚀

PS: Many thanks to Stefan Dobre for reminding me to use the official “isEmpty” function instead of creating a new one.

PPS: Wondering about the picture? It’s The Sphere - a photo taken during my stay at Oracle Cloud World 2024 in Las Vegas

1
Subscribe to my newsletter

Read articles from Rafal Grzegorczyk directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rafal Grzegorczyk
Rafal Grzegorczyk

Oracle APEX & PL/SQL Developer with 10 years of experience in IT, including financial systems for government administration, energy, banking and logistics industry. Enthusiast of database automation. Oracle ACE Associate. Certified Liquibase database versioning tool fan. Speaker at Kscope, APEX World, SOUG, HrOUG, POUG and DOAG. Likes swimming in icy cold lakes in winter and playing basketball.