XForms tutorial - Chapter 11 - Creating a summary page

To make our work a little easier, we move our control resources to another place in the resources instance and modify the references to them accordingly.

<xf:instance id="resources"  xmlns="">
 <resources>   
  <fields>
   <!-- First tab fields -->
   <field name="citizen_company">
    <label>Are you an individual citizen or representing a company?</label>
    <hint>Please make a selection.</hint>
    <alert>This selection is required.</alert>
    <help>Indicate if you apply as a citizen or on behalf of a company.</help>
   </field>
   <!-- Tab 2 fields -->
   <field name="citizen_firstname">
    <label>Your first name</label>
    <hint>Please enter your first name.</hint>
    <alert>This information is required.</alert>
    <help>Your first name could be 'John'</help>
   </field>
   <field name="citizen_middlename">
    <label>Your middle name</label>
    <hint>Please enter your middle name.</hint>
    <alert></alert>
    <help>Not everybody has a middle name.</help>
   </field>
 … etc …

We reference these resources slightly differently now:

<xf:select1 ref="citizen_company" appearance="compact" incremental="true" >
 <xf:label ref="instance('resources')/fields/field[@name='citizen_company']/label" />
 <xf:alert ref="instance('resources')/fields/field[@name='citizen_company']/alert" />
 <xf:help  ref="instance('resources')/fields/field[@name='citizen_company']/help" />
 <xf:hint  ref="instance('resources')/fields/field[@name='citizen_company']/hint" />
 <xf:itemset nodeset="instance('resources')/options/citizen_company/*">
  <xf:label ref="." />
  <xf:value ref="@value" />
 </xf:itemset>
</xf:select1>

By the way, this is a great start for internationalizing a form; all textual resources located in one place. We will get to internationalization in another chapter. Right now, we have resource texts and structure of the wizard stored in such a way that offers maximum flexibility.
First of all, we add a fifth step to our wizard structure and enter a text for the <label>:

<steps>
 <step nr="1">
           …
 </step>
 <step nr="2">
           …
 </step>
 <step nr="3">
           …
 </step>
 <step nr="4">
           …
 </step>
 <step nr="5">
  <label>Application overview</label>
  <summary></summary>
 </step>
</steps>

Then, in the body section of the form, we add this code:

<xf:case id="step_5">
         <xf:setvalue ref="instance('formstate')/fst:currentStep" value="5" ev:event="xforms-select" />
         <xf:dispatch name="custom-setdisplayvalues" targetid="model" ev:event="xforms-select" />
         <xf:group appearance="full">
                   <xf:action ev:event="xforms-select" ev:propagate="stop" />
                   <!-- Iterate over all wizard pages but the last -->
                   <xf:repeat nodeset="instance('resources')/steps/step[@nr!=instance('formstate')/fst:numberOfSteps]">
                            <xf:group appearance="full" ref="@nr">
                                      <xf:label ref="..">
                                               <!-- Display the summary if available -->
                                               <xf:output value="choose(string-length(summary),summary,label)" />
                                      </xf:label>
                                      <!-- Iterate over all elements on this page -->
                                      <xf:repeat nodeset="instance('')//*[@step=current()]" >
                                               <xf:group ref="." class="non-rendering">
                                                        <xf:output value="choose(string-length(@displayvalue),@displayvalue,.)" >
                                                                  <xf:label>
                                                                           <xf:output value="instance('resources')/fields/field[@name=local-name(current())]/label" />
                                                                  </xf:label>
                                                        </xf:output>
                                               </xf:group>
                                      </xf:repeat>
                            </xf:group>
                   </xf:repeat>
         </xf:group>
</xf:case>

This fifth case at the very beginning raises the custom-setdisplayvalues event. This will create readable information for those controls that hold a hard to interpret value for users, such as the index of a list. In this case, we have added a displayvalue attribute only to the first control. Inside the group, this block of code first iterates over each page of the wizard (except the last one, which is the summary page) and then over all controls on that particular page of the wizard, taking into account the relevance of the controls.

The result is a page such as this one:  

Summary page

Figure 20. Summary of user input.

By offering a user such a summary, we provide a user-friendly way to verify all input data. At this point, we would like to make one more modification; what if the user detects he has made a typo or another type of mistake while answering the questions? So we add this block of code to the section above, right after the page label:

<!-- Add a 'go back to edit' button -->
<xf:trigger class="trg_left">  
<xf:label>Edit</xf:label>  
<xf:action ev:event="DOMActivate">   
<xf:toggle>    
<xf:case value="concat('step_',.)" />   
</xf:toggle>  
</xf:action>
</xf:trigger>

Since the reference of the XForms group we are in, is set to @nr already, we can use the . to reference it and determine the case that this section of the summary refers to. Do we have more wishes for our wizard? Yes!

  •  Create summary page as PDF for archiving purposes
  • Temporary save/load

These issues we will address in a later chapter.