Custom Wizard Progress Bar in Oracle APEX

So, you’re making a wizard bar in your APEX app - but there’s something not quite right. The colour isn’t to your liking? Your custom icons won’t work? You’re about to throw away your laptop and give up styling altogether?
No need to stress. This is the guide for you, a quick rundown of the Wizard Progress template - what it does, how it works, and why we might want to manipulate it.
Understanding the Wizard Progress template
The Wizard Progress template can be a great way to display information to users.
By default, the Wizard Progress template has only a handful of substitution variables that we can use, as shown below. If you didn’t know already, you can find these in the ‘Templates’ section of ‘Shared Components’ - just search for ‘Wizard Progress’. You’ll see HTML structure used to construct the template, as well as the substitution strings below.
Substitution string | SQL query column | Description |
n/a | The DOM IDs of the list and each entry. Not recommended to alter these | |
label | The label of the list entry | |
target | The URL target of the list entry (only applicable if the template is made clickable) | |
n/a | is_current_list_entry | Decides the position of the current progress marker. This can either be a ‘YES’ or ‘NO’, if yes then the ‘is-active’ class is added to the <li> in HTML. |
If we wanted, we could add our own substitution strings into the Wizard Progress template definition, and then use these to further customise the progress bar. This would be done through the use of user-defined attributes (#A01# - #A20#) which APEX reserves for such an occasion and if you look in some of the other template definitions, you’ll see these referenced. However, on larger scale projects this might not always be the best option. For example, if an app is upgraded to a newer version of APEX that alters the template at all, then our changes will be lost and the app will likely break. Therefore, in order to future proof our app it is recommended to try and use what’s already there.
Customising the progress bar
To start, I’ll write a simple SQL query which will form a list definition used to display the wizard progress bar as shown below.
SELECT 1 as lvl
, '<span class="' || custom_class_here || '"> </span>' || step_name AS label
, 'f?p=&APP_ID.:' || page_number || ':&SESSION.:' AS target
, CASE
WHEN page_number = :APP_PAGE_ID THEN 'YES'
ELSE 'NO' END AS is_current
FROM wizard_progress_steps
WHERE wizard_code = 'NEW_EMPLOYEE'
AND is_active = 'Y'
ORDER BY step_sequence;This is simply pulling data from a simple table that stores a page number, code and name which is used to populate the wizard. You can also see the SQL query columns form the table above which the template will use to structure the wizard component. We only have the label, link and is_current columns to play with so here is where we have to get creative. FYI, the target column is just a url, so we could also use the APEX_PAGE.GET_URL() function here. If you look at the label column, you’ll see a concatenation of the <span> constructor. This is a cheeky bit of HTML injection that will add our custom class when the code compiles.
If we check the inspect element of the page, we can see it added inside the label class. Great! We can now use this to add a class dynamically from a column in our table, or as part of a CASE clause in the query - giving us much more control over the styling of our progress bar.

To demo this, I’ll write a bit of inline CSS to target our custom class, and change the background colour depending on it, however you can target any of the CSS styles that are used by this class. I’ll also add some to target the ‘is-active’/’is-complete’ classes for more customisation.
.t-WizardSteps-step:has(.custom_class_here) .t-WizardSteps-marker {
background-color: #bf4f4f;
position: absolute !important;
}
.t-WizardSteps-step.is-active .t-WizardSteps-marker {
background-color: #b4bf4f;
}
.t-WizardSteps-step.is-complete .t-WizardSteps-marker {
background-color: #3d2e9e !important;
}And here we can see how it looks on page (ignore the exaggerated colours)

We could even go a step further by checking the label text itself and changing the icons to our own, adding a further layer of customisation. One important thing to note here is that if you want to use the Font Apex icons, you will need to add the ‘fa’ class to the ‘.t-WizardSteps-marker’ component in order for the unicode to match up correctly.
JavaScript
$('.t-WizardSteps-label:contains("Personal Details")')
.closest('.t-WizardSteps-wrap')
.find('.t-WizardSteps-marker')
.addClass('fa personal_details');
$('.t-WizardSteps-label:contains("Address")')
.closest('.t-WizardSteps-wrap')
.find('.t-WizardSteps-marker')
.addClass('fa address');
$('.t-WizardSteps-label:contains("Employment Info")')
.closest('.t-WizardSteps-wrap')
.find('.t-WizardSteps-marker')
.addClass('fa employment_info');
$('.t-WizardSteps-label:contains("Review")')
.closest('.t-WizardSteps-wrap')
.find('.t-WizardSteps-marker')
.addClass('fa review');
$('.t-WizardSteps-label:contains("Confirmation")')
.closest('.t-WizardSteps-wrap')
.find('.t-WizardSteps-marker')
.addClass('fa confirmation');
CSS
.t-WizardSteps-step:has(.personal_details) .t-WizardSteps-marker::before {
content: "\f007" !important;
}
.t-WizardSteps-step:has(.address) .t-WizardSteps-marker::before {
content: "\f015" !important;
}
.t-WizardSteps-step:has(.employment_info) .t-WizardSteps-marker::before {
content: "\f0b1" !important;
}
.t-WizardSteps-step:has(.review) .t-WizardSteps-marker::before {
content: "\f1da" !important;
}
.t-WizardSteps-step:has(.confirmation) .t-WizardSteps-marker::before {
content: "\f00c" !important;
}And here’s the finished product.

Conclusion
And there you have it - a customised Wizard Progress bar, without the worry of future upgrade issues. Now you can ensure your users are blown away by your dynamic, professional UI (at least until the next release).
For more interesting APEX tips, why not check out our guide on What’s new in APEX 26.1?



