Recently I was at the Tech 18 conference in Liverpool where I went to an APEX presentation by Adrian Trotman on the power of lists. During his presentation (which was good by the way), he gave out a challenge to the room. He asked if anyone could make the wizard list type clickable in APEX 18.x, so it would be possible for a user to skip ahead if they have been through the wizard pages before. Unusually for me I discovered I had a spare hour so decided to give it a go. I started off by setting some simple rules to follow.

  • The test application will contain a simple set of pages (let’s say 5) with some required items (One per page will do) controlled by a wizard progress list.
  • The user must visit each new page in turn when entering data for the first time.
  • The user can use the wizard progress bar to navigate directly to any page previously visited.
  • The user can use the wizard progress bar to navigate forward to any page previously visited.

To get started I created a new blank application in an 18.2 environment. I then used the “Create Wizard” wizard to build a set of 5 pages with a single item on each and the associated wizard list.

 

After doing this I set the required value for the test item on each page to “Yes” and then tested the wizard. As expected I had to use the next and previous buttons to move through the pages in turn, clicking on the wizard progress list did nothing.

 

 

Now I had my simple application with a wizard it was time to make the steps in the wizard progress region clickable. There are several ways to do something like this, I first thought about adding some custom JavaScript to manipulate the region at runtime, but I decided to keep it as simple as possible and create a custom template. I ran the page and opened developer mode to inspect the wizard progress region to see what I could make clickable. I discovered that each list item had a <li> entry followed by a <div> at the top level with the class “t-WizardSteps-wrap”.

 

 

Looking at the attributes of the wizard progress list region I could see the template being used was “Wizard Progress”. I opened the templates from shared components and made a copy, calling it “Wizard Progress-Click”.  I then then updated the attributes of each page to use the new template.

 

 

Next I looked for the part of the temple used to render each non-current list item. I decided the simplest option was to make the <li> tag clickable and call a custom JavaScript function, which would pass the page the user wanted to navigate directly to. The function could then determine if the navigation was allowed or not. To do this I added onclick=”javascript:wizardClick(‘#A01#’);” to the list item entry. There did not appear to be any obvious substitution string to use in the function call to identify the page, therefore I used #A01# and added the page number to user defined attribute 1 on each list entry.

I also wanted to make it obvious to the user that the steps were clickable by customising the CSS, so I added an additional class of “wizclick” to parts of the definition and attached a CSS file containing the following to the application.

.t-WizardSteps-wrap.wizclick:hover {
    cursor: pointer;
}
span.t-WizardSteps-marker.wizclick:hover {
    background-color: #de0909;
    cursor: pointer;
}
span.t-WizardSteps-label.wizclick:hover {
    cursor: pointer;
    color: #de0909;
}

The CSS makes the cursor pointer change when the user hovers over any part of the step and also makes the marker and step text change colour. Now the past/future steps were clickable in the wizard progress region, I needed to add the JavaScript function called when a step is clicked. This function would need to check if the user was allowed to navigate to the requested page. For this test application the rule was simple; the user must have previously visited the page to be allowed to navigate directly to it using the wizard progress region. To achieve this all I needed to do was keep track of the maximum wizard page visited. I did this by adding a hidden item to page zero to store the maximum page and an “on-load” application process to maintain it. I also made sure the item was set to NULL when starting the wizard afresh. Next I added the following JavaScript function to the application to validate if the requested page could be navigated to by checking the maximum page visited. If the request is valid an APEX submit is called, if invalid an alert message is displayed.

function wizardClick(vTargetPage) {    
   var vMaxPage = apex.item("P0_MAX_PAGE").getValue();            
   if (vTargetPage > vMaxPage) {
      apex.message.alert("You cannot skip to this page, please use the wizard.");
   } else {
      apex.item("P0_TARGET_PAGE").setValue(vTargetPage);   
      apex.submit({request:'SKIP',validate:true});
   }      
}

Finally to complete the customisation I added a second hidden item to page zero to store the target page and a conditional branch to navigate to the target page when a “SKIP” submit request is made. I now have a simple test application with a five step wizard that allows me to navigate directly to any step (page) previously visited by clicking on the relevant area in the wizard progress region. However when using the wizard for the first time each step must be visited in turn. If you want to take a look at the sample application I have put it on apex.oracle.com. https://apex.oracle.com/pls/apex/f?p=eca_wizclick

Colin Archer Contributor
Senior Oracle APEX Development Consultant , Explorer UK LTD

Colin is a Senior Development Consultant at Explorer with 20 years experience of analysis, design and development of bespoke Oracle applications for a wide variety of business functions. Building on his previous experience of Forms and PL/SQL he is now focusing on developing high quality fit for purpose solutions using APEX.