In my previous article I outlined several best practices that improve the portability and readability of workflows in Geocortex Workflow. This article will address complex form navigation in your workflow. A working sample of the workflow described below is available here.
When presenting a user with a series of form-based questions, it is important to design your workflow in a manner that allows the user to move back and forth seamlessly. People make mistakes or change their minds, and nothing is more frustrating than having to cancel and start over after an error. Therefore, each form must include navigation buttons. The names of the buttons may vary, depending on the user experience paradigm you follow, but are typically are: “Back”, “Next” and “Cancel”.
Adding buttons to a form in Geocortex Workflow is simple. Accessing the values is similarly easy as the clicked button’s value is provided in the form’s result. For example, in the sample below, if the user clicks “Next”, then the $form3.result value will be “Next” (or whatever the “Next” button’s value is set to in the form).
Pretty easy so far. Using the form result we can navigate the workflow and in cases when there are a small number of forms (2 or 3) this is likely all that’s necessary. However, what about cases where we have a larger number of forms? Stringing together a bunch of forms and business processes executed as an outcome of the form input will quickly result in an unreadable plate of spaghetti.
In my previous article I noted that Geocortex Workflow containers should be used to group activities into a single action (initialize variables, select features, etc.). Workflow forms similarly can be grouped into containers. The grouping may be more arbitrary than a business process since there may be no clear delineation between sets of forms, but the idea is to create manageable groups that a developer can easily read and navigate.
Global Navigation vs Container Navigation
The best way to manage the navigation state of a workflow is by scoping variables both within containers and globally. At the container level, the navigation state can be collected and inspected following each form submission. In the sample below, form2’s result is inspected using the Container Nav switch. The cases (“Next,” “Back,” “Cancel”) direct the user to the appropriate form or action.
Navigating between containers gets trickier since a switch activity’s case can only connect to activities within the current container’s scope. Using a globally scoped navigation variable gets around this problem. In the initialization container, I define a variable to hold the global navigation state named navState. The default state is set to “Next” so that when we enter the first container, we are directed to the first form.
We can then use the same switch pattern to navigate between containers at the global scope. The example below illustrates navigating between the Forms Group 1 and Forms Group 2 containers via Global Navigation Switch activities.
The global navigation variable bridges the gap between each container. It is set when a user chooses a path that leads out of a container. The example below illustrates the 3 possible states being set from the container navigation Switch activities. If the user is in the first form in the container and chooses to move back then the state of the global navigation variable is set to “Back”. Similarly, if the user chooses “Next” in the last form, the global navigation variable is set to “Next”. Choosing to cancel sets the global navigation to “Cancel”.
The state of the global navigation variable is also checked first when entering a container. This is to determine whether the user is navigating forwards (“Next”) or backwards (“Back”) in the workflow. If the global navigation is backwards, then the user is directed to the last form in the container. The container navigation will then be able to direct the user accordingly.
You may notice that in the samples above that the cancel state is bubbled up to the global scope rather than simply dropping out of the workflow within the container using the exit activity. This is to reduce redundancy as well as provide a single location for managing the clean up of your workflow. All exit navigation ultimately ends in the Clean Up and Exit container. In my example, this container only includes the exit activity and some logging but this is an ideal place to clear graphics, remove selections or otherwise tidy up the viewer prior to ending the workflow.
Form navigation within your workflows can quickly become difficult to manage when many forms are required. Good user experience (UX) design dictates that the end user must be provided the opportunity to freely navigate forwards and backwards within a forms-based application. By applying the pattern described above, it is possible to create a workflow that meets this UX requirement while remaining readable and easy to maintain. Furthermore, the pattern can easily be reused for other workflows, thus reducing development effort.
Want to learn more about Geocortex Workflow? Visit the Geocortex Workflow 5-Series Community. You can ask questions, view the latest discussions or get in touch with our support team.