How to make your mobile APEX application look like a native one - Part 2

Photo by on Unsplash

How to make your mobile APEX application look like a native one - Part 2

Build mobile friendly forms


10 min read


This is the second part of a series of blog posts on customizing the look and feel of the Oracle APEX mobile application to mimic a native application. You can read part one on the general look and feel of the application here. This part will focus mainly on creating mobile-friendly forms to make your users happy to use your application. You'll see that by using the right input type or adding a simple attribute, you can completely change your application. Let's see it!

The layout of the form

My main advice for the layout of the forms is to rely on the default settings of the Universal Theme. At the time of writing this article, the current version of APEX is 22.1 and it does a very good job of handling the layout of entries for the various screen sizes.

Here is three simple topics that I want to talk about:

  • Always use a single column layout, it is easier to read and fill in. In fact, the Universal Theme did a very good job with this and I had to use CSS Responsive Classes to take this screenshot.

Screenshot showing the differences between single column and multi column layout

  • Use the floating (default) or above page item template option, this will save space and make the forms more readable. My preference is for the floating labels but if you must use the above option, try using the Large or X Large item size to facilitate tactile interactions. Nothing is more annoying than selecting the wrong input on a form.

Screenshot showing the differences between the item template above and the floating one

  • This brings us to the final tip on form layout: don't change the default spacing of items. You'll save space, but you'll irritate your users by leading them to a wrong input selection. See the screenshot below, do you really think it's possible to use it with your fingers?

Screenshot showing the differences of removing the item spacing or keep the default value

Choosing the right input types

HTML has many input types and they are there for a reason, so use them! As we develop applications using APEX, we won't have total control over the markup but we rely on choosing the right page item type with the right option. But, sometimes, you'll see, adding a simple HTML attribute can change everything.

The virtual keyboards are important

When targeting mobile devices, your users will need to use virtual keyboards and not real keyboards like computer users. This is very important because you can help them by choosing the right item type and attribute option. Here is a screenshot of the different keyboards I get on my Android mobile depending on the type I defined:

Screenshot showing the different types of virtual keyboard available depending on the item type defined

Believe me, having the right keyboard will make your users happy to fill out your forms. For example, the one associated with the email type field got the "@" to the right of the space bar or the one associated with the phone number type, got the keys needed to enter the prefix and numbers. The good thing is that, for the most part, it is completely handled by APEX, by choosing the right attribute on the Text Field item type :

Screenshot showing the options available for the Subtype attribute of a Text Field item type

But sometimes you want to change the default behavior and you can use the inputmode attribute to do so. For example, I had to use it for the Number field because, by default, it only displayed a normal keyboard (the same as a Text field). To correct this, I added the attribute inputmode="decimal"

Screenshot showing how to add the inputmode attribute to a page item

Improving date and time entry

If you are developing with Oracle APEX and need to enter dates and/or times, you will choose the Date Picker item type, which makes sense, but don't forget to change the attribute under Settings\ Display As to "Native HTML".

Screenshot showing where you can choose the display option for the date picker item

You will ask why I recommend changing the default option. Then I think the best answer is to show you the difference

Screenshot showing the differences between the regular date picker using Oracle JET and the Native HTML version

Oracle APEX implements the input type "date" and "datetime-local" depending on whether the attribute "Show Time" is turned on or off. But there are three other types available which are "time", "week" and "month". It is possible to use it by choosing the item type "Text Field" and modifying the type attribute during the page loading by adding this JavaScript code:

// Change the type of the item P3_HOUR to time
apex.jQuery("#P3_HOUR").attr("type", "time"); 
// Change the type of the item P3_WEEK to week
apex.jQuery("#P3_WEEK").attr("type", "week"); 
// Change the type of the item P3_MONTH to month
apex.jQuery("#P3_MONTH").attr("type", "month");

Here are the screenshots of the different types available and how the operating system provides you with a specific user interface to fill in the fields

Screenshots displaying the 5 differents types of input date, datetime-local, time, week and month with their specific UIs

Improving standard file browsing

Oracle APEX provides a File Browse item type to allow users to upload files via an application. We can make the experience much better on mobile devices by using the capture attribute

Code snippet displaying the use of the capture attribute to record images, videos and audios

Here is how you can add it to a page item inside the APEX builder

Screenshot showing where you can add the capture attribute to a page item

To see it in action, I recorded a little video. Pretty cool, isn't it?

Note: I tested it on an iOS device and it appears that the microphone option was not working on this browser. This is the limit of the web developement, we rely on how each browsers implements the standard specification.

Autocomplete is your friend

HTML has an attribute (autocomplete) that allows your users to reuse some information already stored in their browser like email, phone number or addresses. It is particularly useful for registration pages to speed up the filling of the form, here is an example:

Animated screenshot showing autocomplete form

So how do you apply it? Just add this attribute with the value of your choice under Advanced - Custom Attributes:

Screnshot showing how to define the autocomplete attribute on a page item

I recommend looking at the different values of this attribute to have full control over the autocomplete of your forms (there are many options available). But, more importantly, sometimes you'll want to disable it altogether and you can do that by using autocomplete="off". While writing this post, I found that Chrome was acting a little differently by not implementing the off value correctly. You can fix this behavior by using autocomplete="chrome-off" to target that browser. Here is the JavaScript code I used to handle it:

// Targeting Chrome only
if ( navigator.userAgent.includes("Chrome") ) {
   // Loop through inputs for which we want to disable autocomplete
   apex.jQuery('input[autocomplete="off"]').each(function() {
      // Replace the attribute value by the chrome specific one
      apex.jQuery(this).attr("autocomplete", "chrome-off");

Clearly validate the user's input

Choosing the right display location

Speaking of validation the first tip is to always set the attribute "Display Location" to "Inline with Field" and select the page item into "Associated Item"

Screenshot showing the attribute Display Location on a validation

Why should you use this? Because this way your user will clearly see which entries are invalid and why. If you display the validation as a notification or worse on an error page, it will be very difficult to see it on a mobile device.

Screenshot comparing validation messages displayed inline with field or in notification

Validation on the client side

When targeting mobile devices, you need to understand that filling out forms can be time consuming if you have to come back to correct entries. A good solution to avoid this is to perform client-side validation as the user types.

Animated screenshot showing an example of client-side validation while user entered a value

Here is the code used to register this example, first I defined a JavaScript function called validateForm under the Function and Global Variable Declaration attribute of the page

function validateForm() {
    let errors = [];
    // Validate only if the field is not empty
    if ( apex.items.P5_USERNAME.isEmpty() === false ) {
        // Display an error if you someone try to use my first name
        if ( apex.items.P5_USERNAME.value === "Louis" ) {
                    type:       "error",
                    location:   "inline",
                    pageItem:   "P5_USERNAME",
                    message:    "Username is not available.",
                    unsafe:     true
    // Raise an error if the field is not empty and not valid
    if (apex.items.P5_EMAIL.isEmpty() === false && apex.items.P5_EMAIL.getValidity().valid === false) {
                type:       "error",
                location:   "inline",
                pageItem:   "P5_EMAIL",
                message:    apex.items.P5_EMAIL.getValidationMessage(),
                unsafe:     true


I then called this function under the Execute when Page Loads attribute. Note that we use apex.util.debounce to add a delay while users enter data to reduce the number of validation executions.

apex.jQuery( "input" ).on( "keyup", apex.util.debounce( validateForm, 200) );

I you want to know more about client-side validation, I recommend you to read a great blog post of my colleague Plamen Mushkov on email address validation here. Another great read is this post by John Snyder.

A final note on this subject, even if you perform client-side validation, I recommend that you always perform server-side validation as well. You can never be too careful!

Format your items or at least give a hint

When requesting formatted information such as credit card number, phone number, or IP address, it's a good idea to always give your user a hint as to what format you expect. Nothing is more annoying than typing an entry and realizing that you forgot to add the separator that is needed to validate the field. You have two main options for this in Oracle APEX, the help text and the placeholder. The main advantage of the first option is that it will be present even if you have started typing the value.

Screenshot of the inline help text to help users to know the expected format

Another option is to use a JavaScript library such as JQuery Mask Plugin o help your user enter the value and ensure that you get the format you expect. Using this library is quite simple in APEX :

  1. Add the library to the page under JavaScript \ File URLs. I used the CDN here but you can download the file and add it to the static application files.

Sreenshot showing the attribute where you can define JavaScript file urls to include to your page

  1. Add the data-mask attribute to the items under Avanced \ Custom Attributes. Here is the example I used to mask the credit card number

Screenshot displaying where to define the data-mask atrribute on a page item

  1. Run your page!

Animated screenshot showing the Jquery Mask Plugin in action

I find that with minimal effort, you can greatly improve the user experience by combining the addition of accurate help text and an automatic mask.


In this article, we have seen that we can greatly improve the user experience by sometimes adding a simple HTML attribute like inputmode to change the default keyboard. Or by using a third party library that will help you validate user input or get the value in the format you expect. I think the main point here is to decide the time you want to spend to customize the look and feel of your application. Fighting against native apps even with PWAs is not easy, but you can surely build something really good.

I really hope you enjoy reading this blog post as much as I enjoyed writing it ๐Ÿ˜Š. I will continue this series but I don't know at this time what the next one will be about. Stay tuned!