I was recently asked to implement a fairly large and complicated form in APEX. Rather than displaying something long and scary to users on a single page, we decided to break it out into sections on different pages, and use a Sidebar Navigation Region that would show the user which section he/she was currently filling out, and where in the process he/she was, as in the example below. By the way, this also happened to be the same form in which I implemented a simple yet powerful workflow using Dynamic PL/SQL.
We decided to use the Progress Wizard List Template, and with that, we were pretty much 80% of the way there. Gotta love APEX! We just needed to make a few small tweaks.
1.We wanted the user to be able to navigate to a specific section of the form by clicking on the relevant sidebar link on the left. This meant branching to a different page.
2. We also wanted to trigger an automatic save (SUBMIT) of the form when he/she clicked on the relevant sidebar entry, without having to click on the ‘Save’ button.
1. Created a Page 0
2. Added the following (hidden) item to Page 0: P0_BRANCH_PAGE
3. Added an After Submit branch to each of the pages involved in the workflow, branching to page P0_BRANCH_PAGE (using the &P0_BRANCH_PAGE. syntax).
4. Created my list using the Wizard Progress template.
5. I used the User Attributes section of each list entry to track the branch page. This way, I could refer to it in my template using #A01# substitution. Here’s an example of my ‘Step 1’ list entry, which I want to branch to page 1:
6. I modified the template of my Progress Wizard from the following:
to
The apex.submit line performs 2 actions at once: sets the value of REQUEST to ‘SAVE’, but also sets the value of the P0_BRANCH_PAGE item. You can set any number of items using this method, but careful, I have found that it does not appear to work if the item is on the current page (not sure why…).
Voilà, as easy as that! Users are now able to navigate to any section of the form by clicking on the wizard, and their changes get saved automatically. Was this the best way to go about it? Not sure, but it works great. If you have any comments or suggestions on how else I could have accomplished this, I’d love to hear them!
Very cool solution, love the simplicity and elegance. Well done!
Hi,
You could break down the page/form in different sections by using regions instead of pages and display one region at a time by using show/hide dynamic actions (or using tabs like offered by the JQuery UI).
Cheers,
Christian
Thanks Christian! Actually, the form was so large that I would possibly have exceeded the 100 items per page limit of APEX, which was one of the main reasons I decided to break it out into multiple pages. That was when I hit the issue of needing to save before switching to a new page. Thanks for your comment!
I also need to create a workflow type Apex app. I was searching several of the Apex web sites and the Forum for ideas and came across your article.
It is really well done. I especially like its simplicity and, together with your “complimentary” implementaion (displaying table-driven buttons based on user role and document status), it’s a great marriage of the two concepts.
Thank you for sharing these.
Let me ask …
In my own project, I need to minimize the potential of users losing their form data due to, say, a browser crash or an Apex timeout. At first, I thought of placing all user entered form data into Apex collections. When the user completed filling out several forms, they would click a “SAVE” button to commit their entries to Oracle.
Trouble is, my users tend to leave the browser un-attended for long stretches of time, leaving them open to an Apex timeout or, possibly, a browser crash, thus losing all their data. This equates to frustrated users.
And so, I thought of setting up a “timer” of sorts that would automagically save all entered form data to Oracle tables, say, every 60 seconds. In fact, there’s a “Timer” plug-in for this available on the apex-plugin.com web site.
And so, I am wondering if you’ve used this table approach to save form data or do you recommend using Apex collections?
And if you do use the table approach, then what do you do to *uniquely* identify a data set for a given user, since the same user may work on the same set of data or on different sets of data at many times during the day?
Thank you for any advice. It’s much appreciated.
Elie
Hi Elie,
I am glad you found the posts helpful, thank you for your comments.
With regards to your question, first of all I would say that it sounds like you users need to be educated a bit about working with a database and browser! Of course they need to Save occasionally to keep from losing their work. Sometimes we developers spend too much time trying to fix issues that are really about user education, I think.
I am not crazy about the idea of regularly timed ‘Save’ without the user taking some sort of action to indicate that this is what they really want to do…
That being said, did you know that you can control the APEX Session Timeout variable? It sounds like this is something you may want to consider.
With regards to collections, I do not use these for the purposes you describe. I tend to use them only when I need to store something that is really only relevant to the user and that particular session. For example, report parameters or something similar. Otherwise, for data display and manipulation, I fetch the data into APEX page items/regions, and update data directly to the Oracle tables when the user clicks Save (or moves on the the next step, as above). Of course, every project is different, and until I really know what it is you are trying to accomplish, it is difficult for me to say. But I do not really see how collections will help you with your browser issue. Increasing the timeout and user education sounds like a better way to go!
In terms of uniquely identifying a data set, your tables must have primary keys defined, I assume? You fetch and update them accordingly? Again, I am not exactly sure what business problem you are trying to solve here in terms of uniquely identifying a data set. If it helps, though, the APEX Session ID is unique to a user’s particular session, so I suppose that that in combination with the table’s primary keys might help you? In terms of creating some sort of unique data set? Or you could use a timestamp?
Hope some of this helpful.
Best,
Michelle
Hi, Michelle.
Thank you very much for your advice. They are very helpful indeed.
I work as an Oracle database and Apex designer at Stanford University’s Linear Accelerator Center (SLAC) in Menlo Park, CA. For this project, I need to supply physicists with an Apex interface by which they can create/modify a series of questions and associated possible choices (displayed as text fields, checkboxes, radio boxes, drop downs). This set of data may go through multiple “revisions” before being saved as a bonafide “version” in underlying Oracle tables.
My challenge here is presenting an intuitive workflow these scientists can follow (this is where your informative article is so helpful – thank you again) and making sure these intermediate “revisions” are saved such that they may be retrieved whenever the physicist returns to making further changes. Once the sphysicist decides no more changes are needed, then a “Commit As Version #n” button would allow the current revision to be saved in Oracle with a unique version number.
I asked your opinion about collections because I wanted to be sure a revised set of data (a “revision”) is safely stored such that it may be retrieved next time more work is done on it. These physicists are, in general, a pre-occupied lot, tendng to step away from their PC’s or mobile phones (whereever they choose to run my Apex app) for long periods while they tend to running experiments. My concern is that, even with setting the Apex session timeout variable to a long period, there is medium to high risk of a set of changes being “lost” due to PC crash or mobile phone crash or pressing the wrong button on the phone or “who knows”. The net affect would be frustrated scientists.
And educating our users to periodically click a supplied “Save Your Changes” button is further challenged by the fact that my customers/physicists are often spread out all over the world, using a multiplicity of languages, not to mention cultures.
I’ve completed the underlying database design (tables, constraints, views, triggers, etc.) and am now working on the Apex application. And so, when I saw your article on workflow I figured I would pose my “save revision” question to get your feedback.
Thank you, again, for a great blog and your help. I also liked reading the other articles you’ve posted, about “JQuery ClueTips” and the one about “Integrating Oracle Text with Apex”. Good stuff.
Thank you, again.
Elie
Michelle,
I have a couple of questions.
1) I created a List object under Shared Components and assigned it the Wizard Progress template as per your article. I then created a static list and entered the “target” pages (pages 20, 30, and 40). What is the purpose of setting these target pages. When I run my Apex app, the list displays but none of the 3 list entries are “clickable”. I *thought* that was the purpose of setting these target pages. Frankly, this puzzles me because, if Apex already provides the means to assign url type “target” pages when creating a List widget, then why in your article do you describe modifying the List template so that the list entries are clickable. It did not seem necessary. However, I am unable to make these assigned “target” pages clickable.
2) What Apex theme did you use to create the nice colors of your List navigation widget? I’ve tried various themes but can’t get the red color of the current list entry the way you display in your article.
Thanks, again, for your help.
Elie
Hi Elie,
The fact is, the ‘Target’ element of the list is only really relevant if the template your list uses makes reference to it. I populated it because it is a mandatory field, but if you notice the default Progress Wizard template (under Shared Components –> Templates), neither the List Template Current not the List Template NonCurrent make reference to it. That was actually one of the main points of the post, was to show how to modify the template first to make it clickable, and then to make it set a value and save. This is covered in Step 6. If you simply want to make it clickable and are not concerned with the ‘Saving’, you could modify your template to the following:
<li class=”current”><a href=”#LINK#” rel=”nofollow”>#TEXT#</a></li> (notice the anchor tag that is not there by defaut).
In terms of the color, my demo used the ‘Scarlet’ template, however you could always modify the look and feel by using your own stylesheet, or including a modified version of the wizard progress styles in your page header.
Hope this helps!
Hi, Michelle.
Thank you very much for the explanation. I had not worked with Apex Lists prior to this current project, and so, was wondering why the “target” field did not appear to be doing what I thought it should be.
Hmm. I suppose the actual Apex docs would explain all this, especially what you mentioned:
“the ‘Target’ element of the list is only really relevant if the template your list uses makes reference to it”.
I think I need to do some homework and read up on this.
Thanks, again, for your help. Also, I do hope you keep up your article writing. It’s much appreciated.
Elie