Although some applications only require multiple-choice fields where only a single value may be chosen, in many situations it is desirable to be able to choose an arbitrary number of values for a particular field. However, up to this point, we have been content to represent form data using a single attribute on a single element to represent any given field value. With multivalued fields, we must choose a different strategy in using XML to represent such information.
Let us consider permitting multiple type values to be associated with our items. We revise our form data structure to be the following:
<?xml version="1.0"?>
<structure>
<item value="some value">
<type>
<type-enum value="some type"/>
<type-enum value="some other type"/>
</type>
<subitem subvalue="some other value"/>
</item>
</structure>
We shall now take advantage of those HTML form fields which permit users to select one or many values presented in a list or menu.
Some item:
Item type:
Itself containing more items:
Sub-item:
From the item type list many value may now be selected.Taking the example HTML code from before, we can add a definition of this new list to the template to produce something like this:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:template="http://www.boddie.org.uk/ns/xmltools/template">
<head>
<title>Example</title>
</head>
<body template:element="structure">
<form action="" method="post">
<!-- Template text between the start and the interesting part. -->
<div template:element="item">
<p>
Some item: <input template:attribute-field="value" name="..." type="text" value="..." />
<input name="..." template:selector-field="remove" type="submit" value="Remove" />
</p>
<p>
Item type:
<select name="..." template:multiple-choice-list-field="type,type-enum,value" multiple="multiple">
<option template:multiple-choice-list-value="type-enum,value,selected" value="..." />
</select>
</p>
<p>
Itself containing more items:
</p>
<p template:element="subitem">
Sub-item: <input template:attribute-field="subvalue" name="..." type="text" value="..." />
<input name="..." template:selector-field="remove2" type="submit" value="Remove" />
</p>
<p>
<input name="..." template:selector-field="add2,subitem" type="submit" value="Add subitem" />
</p>
</div>
<p>
<input name="..." template:selector-field="add,item" type="submit" value="Add item" />
</p>
<!-- Template text between the interesting part and the end. -->
</form>
</body>
</html>
From the previous single-valued case, some crucial changes have been made:
select
element remains mapped onto the type
element in the form data structure. However, we use a different attribute, template:multiple-choice-list-field
, to indicate that a type
element is created when the form data is submitted, but instead of a single value being added to the value
attribute of that one element, a separate type-enum
element is created within the type
element with a value in its value
attribute for each value submitted. This means that many type-enum
elements may be created within the type
element, and each one of them will have a different value
attribute.select
element now has a multiple
attribute defined to permit multiple value selections.select
element, the option
element now employs the template:multiple-choice-list-value
annotation.Unlike in the single-valued case, the revised the form data structure for input is almost the same as the structure used by the template. Indeed, the subtle differences cannot be represented in our simplistic presentation of the structure:
<?xml version="1.0"?>
<structure>
<item value="some value">
<type>
<type-enum value="some type"/>
<type-enum value="some other type"/>
</type>
<subitem subvalue="some other value"/>
</item>
</structure>
In fact, the principal difference arises through the number of type-enum
elements that occur in the input, representing the values selected by
the user, and the number that occur in the output, representing the
complete range of values available for selection.
In most respects, the presentation of the extra values is the same
as in the single-valued case. The result of the presentation of the
extra values is that the type
element in the
this example structure fragment...
<type>
<type-enum value="(Not selected)"/>
<type-enum value="Important" value-is-set="true"/>
<type-enum value="Not important" value-is-set="true"/>
<type-enum value="Personal"/>
</type>
...is transformed into something resembling this HTML code:
<select name="..." multiple="multiple">
<option value="(Not selected)">(Not selected)</option>
<option value="Important" selected="selected">Important</option>
<option value="Not important" selected="selected">Not important</option>
<option value="Personal">Personal</option>
</select>
Above, the special value-is-set
attribute is an XSLForms mechanism to remember which values were set.
Fortunately, the document initialisation mechanism automatically
distinguishes between different multiple-choice field types and
understands where the above approach needs to be employed.
To update the special WebStack resource, we now need to modify a few of the class attributes and to add a few others:
template_resources = {
"structure" : ("structure_multivalue_template.xhtml", "structure_output.xsl")
}
With these adjustments, it should now be possible to manipulate the
items and subitems whilst specifying multiple type values on each item.
Note that it may be necessary to remove the old stylesheet for
producing output, structure_output.xsl
, so that the
multivalue version of the template is taken into use.
In the application we have been developing, we have been content to show the multiple-choice values as they are known in the application - that is, the application refers to values like Personal
and the same text is shown to users of the application. However, there
are various situations where this is not desirable, and the usage of separate labels is described in the next section of the development process.