Create a wizard or multi-page form with Form Builder

With Orbeon Forms 4 and newer, the solution described in this page is obsolete as Orbeon Forms 4 provides a built-in multi-page view. See the Wizard View documentation for more information.

Availability

This solution is known to work with Orbeon Forms 3.9 and 4.x.

The problem

You would like to split a forms into multiple parts shown in sequence, as in a wizard. (We intentionally use the word parts instead of pages even if you can for now think of those as equivalent.) You want to do this because you don't want to overwhelm users by showing a large number of fields, or because some part may or may not need to be filled based on previous answers.

The solution

At this point, Form Builder does not handle "page navigation" or "workflow". With Form Builder, you create one form at a time. When the form is filled out, you can send users to another page you created on another system. The data entered by users can also be passed along to that other page, so it can decide what to do next, which may include redirecting users to another form you created with Form Builder. To learn more about this, see the workflow send button. In what follows, we'll assume that what you want to build is more like a wizard than something that requires an external workflow orchestrating multiple forms.

Example

Let's create a registration form with 3 parts:
  1. In the first part, we'll ask users about their name and if they need a hotel reservation.
  2. In the second part, if they said they need a hotel, we'll ask some hotel-related information.
  3. The third part has just a confirmation message.

Showing one section at a time

Instead of creating multiple forms, you create one, and put each part of your form in a form section. You then write section visibility rules so only one is visible at a given point in time. But how do we know which section to display? Let's create a first section with one field used to keep track of the visible part:


You never want that section to be shown to users, so set its visibility to false(). Name the field part, so you can refer to its value later as $part, and set its initial value to personal, which identifies the part you want to display first.




Create one section per "part", and for each section decide whether it is visible or not based on the value of $part.



Switching from one section to the next

Now you have sections that show depending on the value of $part. But how do you change $part? How do you implement a Next button that goes to the following section? For this you need a bit of XForms coding. To add or edit the XForms code produced by Form Builder, in the left side-bar, under Advanced, click on Edit Source. Then, just below the </fr:body> add:

<fr:buttons>
    <xf:trigger xxf:modal="true"
                ref=".[instance('fr-form-instance')/internal/part != 'confirmation']">
        <xf:label>
            <xh:img width="16" height="16"
                    src="/apps/fr/style/images/pixelmixer/right_16.png" alt=""/>
            <xh:span>Next</xh:span>
        </xf:label>
        <xf:setvalue ev:event="DOMActivate" ref="instance('fr-form-instance')/internal/part"
                     value="
                         if (. = 'personal') then 
                             if (instance('fr-form-instance')/personal/need-hotel = 'true')
                             then 'hotel' else 'confirmation'
                         else if (. = 'hotel') then
                             'confirmation'
                         else ''"/>
    </xf:trigger>
</fr:buttons>

NOTE: You need to make sure the namespace prefixes are in scope. With Orbeon Forms 3.9, use the longer xhtml and xforms prefixes instead.

Depending on your level of familiarity with XForms, you'll either find this trivial or cryptic. Two parts are interesting in this code:
  • The ref attribute on the <xf:trigger> says that the button itself is only visible if we are not on the confirmation part.
  • The ref attribute on the <xforms:setvalue> defines what the new part name is when the button is pressed. In this case it skips the hotel if users said they don't need a hotel reservation.
  • NOTE: Orbeon Forms 3.9 used the <fr:button> control, but Orbeon Forms 4.0 favors <xf:trigger>.

Including custom buttons

Explicitly providing your own buttons inside an <xf:trigger>, placed inside the <fr:view> just after the </fr:body>, overrides the buttons you configured with oxf.fr.detail.buttons. If you want to include other buttons, you need to include them explicitly inside the <fr:buttons>, before or after your custom <xf:trigger>, as in:

    </fr:body>
    <fr:buttons>
        <fr:save-button/>
        <xf:trigger>
            <!-- Code for your custom button here -->
        </xf:trigger>
    </fr:buttons>
</fr:view>

You can see all the possible buttons you can use in buttons.xsl.

Get the source

To try a full example, create a new form in Form Builder, do Edit Source, and paste the content of the attached file there.

ċ
Alessandro Vernet,
Jan 7, 2011, 4:40 PM
Comments