paulb@615 | 1 | <?xml version="1.0" encoding="iso-8859-1"?> |
paulb@141 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
paulb@270 | 3 | <html xmlns="http://www.w3.org/1999/xhtml"><head> |
paulb@141 | 4 | <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type" /> |
paulb@615 | 5 | <title>Creating Applications: Adding Multiple-Choice Fields and Values</title> |
paulb@270 | 6 | <link href="styles.css" rel="stylesheet" type="text/css" /></head> |
paulb@141 | 7 | <body> |
paulb@141 | 8 | <h1>Creating Applications: Adding Multiple-Choice Fields and Values</h1> |
paulb@656 | 9 | |
paulb@141 | 10 | <p>Up to this point, we have only considered two kinds of Web form |
paulb@141 | 11 | fields: text entry fields and action buttons. Since most Web forms |
paulb@141 | 12 | offer more convenient ways of entering certain kinds of data, we shall |
paulb@141 | 13 | now investigate multiple-choice fields as an example of how XSLForms |
paulb@141 | 14 | handles more complicated types of fields.</p> |
paulb@656 | 15 | |
paulb@141 | 16 | <p>We shall revise our <a href="data.html">form data structure</a> to |
paulb@141 | 17 | be the following:</p> |
paulb@656 | 18 | |
paulb@656 | 19 | <pre><?xml version="1.0"?> |
paulb@656 | 20 | <structure> |
paulb@656 | 21 | <item value="some value"> |
paulb@656 | 22 | <type value="some type"/> |
paulb@656 | 23 | <subitem subvalue="some other value"/> |
paulb@656 | 24 | </item> |
paulb@656 | 25 | </structure></pre> |
paulb@656 | 26 | |
paulb@141 | 27 | <h2>Single-Valued Fields</h2> |
paulb@656 | 28 | |
paulb@141 | 29 | <p>Whilst HTML offers types of form fields where users can select one |
paulb@141 | 30 | or many values presented in a list or menu, we shall first consider the |
paulb@141 | 31 | case where only a single value can be chosen from such a selection.</p> |
paulb@656 | 32 | |
paulb@145 | 33 | <form method="post" action="" name="single"> |
paulb@615 | 34 | <p>Some item: <input name="value" value="some value" /><input name="remove" value="Remove" type="submit" /></p> |
paulb@141 | 35 | <p>Item type: |
paulb@656 | 36 | <select name="type"> |
paulb@656 | 37 | <option>(Not selected)</option> |
paulb@656 | 38 | <option>Important</option> |
paulb@656 | 39 | <option>Not important</option> |
paulb@656 | 40 | <option>Personal</option> |
paulb@656 | 41 | </select> |
paulb@141 | 42 | </p> |
paulb@141 | 43 | <p>Itself containing more items:</p> |
paulb@270 | 44 | <p>Sub-item: <input name="subvalue" value="some other value" /><input name="remove2" value="Remove" type="submit" /></p> |
paulb@141 | 45 | </form> |
paulb@656 | 46 | |
paulb@656 | 47 | <p>From the item type list only one value may be selected.</p> |
paulb@656 | 48 | |
paulb@615 | 49 | <p>Taking the example HTML code from before, we can add a |
paulb@141 | 50 | definition of this new list to the template to produce something |
paulb@141 | 51 | like this:</p> |
paulb@656 | 52 | |
paulb@656 | 53 | <pre> |
paulb@656 | 54 | <html xmlns="http://www.w3.org/1999/xhtml" |
paulb@656 | 55 | xmlns:template="http://www.boddie.org.uk/ns/xmltools/template"> |
paulb@656 | 56 | <head> |
paulb@656 | 57 | <title>Example</title> |
paulb@656 | 58 | </head> |
paulb@656 | 59 | <body template:element="structure"> |
paulb@656 | 60 | <form action="" method="post"> |
paulb@656 | 61 | |
paulb@656 | 62 | <!-- Template text between the start and the interesting part. --> |
paulb@656 | 63 | |
paulb@656 | 64 | <div template:element="item"> |
paulb@656 | 65 | <p> |
paulb@656 | 66 | Some item: <input template:attribute-field="value" name="..." type="text" value="..." /> |
paulb@656 | 67 | <input name="..." template:selector-field="remove" type="submit" value="Remove" /> |
paulb@656 | 68 | </p> |
paulb@656 | 69 | <span style="font-weight: bold;"><p></span> |
paulb@656 | 70 | <span style="font-weight: bold;">Item type:</span> |
paulb@656 | 71 | <span style="font-weight: bold;"><select template:multiple-choice-field="type,value" name="..."></span> |
paulb@656 | 72 | <span style="font-weight: bold;"><option template:multiple-choice-value="type-enum,value,selected" value="..." /></span> |
paulb@656 | 73 | <span style="font-weight: bold;"></select></span> |
paulb@656 | 74 | <span style="font-weight: bold;"></p></span> |
paulb@656 | 75 | <p> |
paulb@656 | 76 | Itself containing more items: |
paulb@656 | 77 | </p> |
paulb@656 | 78 | <p template:element="subitem"> |
paulb@656 | 79 | Sub-item: <input template:attribute-field="subvalue" name="..." type="text" value="..." /> |
paulb@656 | 80 | <input name="..." template:selector-field="remove2" type="submit" value="Remove" /> |
paulb@656 | 81 | </p> |
paulb@656 | 82 | <p> |
paulb@656 | 83 | <input name="..." template:selector-field="add2,subitem" type="submit" value="Add subitem" /> |
paulb@656 | 84 | </p> |
paulb@656 | 85 | </div> |
paulb@656 | 86 | <p> |
paulb@656 | 87 | <input name="..." template:selector-field="add,item" type="submit" value="Add item" /> |
paulb@656 | 88 | </p> |
paulb@656 | 89 | |
paulb@656 | 90 | <!-- Template text between the interesting part and the end. --> |
paulb@656 | 91 | |
paulb@656 | 92 | </form> |
paulb@656 | 93 | </body> |
paulb@656 | 94 | </html> |
paulb@656 | 95 | </pre> |
paulb@656 | 96 | |
paulb@141 | 97 | <p>There are a lot of details here that need to be explained. Here is |
paulb@141 | 98 | what was done:</p> |
paulb@656 | 99 | |
paulb@141 | 100 | <ol> |
paulb@141 | 101 | <li>A paragraph was added to provide some space on the page for the |
paulb@656 | 102 | field.</li> |
paulb@615 | 103 | <li>Inside the paragraph, next to the label text, an HTML <code>select</code> |
paulb@656 | 104 | element was added.</li> |
paulb@615 | 105 | <li>The <code>select</code> element is mapped onto the <code>type</code> |
paulb@656 | 106 | element in the form data structure, indicating using a special |
paulb@656 | 107 | <code>template:multiple-choice-field</code> attribute that the |
paulb@656 | 108 | <code>value</code> attribute of the <code>type</code> element will |
paulb@656 | 109 | contain any chosen value from the list of values displayed in the page.</li> |
paulb@615 | 110 | <li>Inside the <code>select</code> element, we include an <code>option</code> |
paulb@656 | 111 | element which defines the values which will be presented to users |
paulb@656 | 112 | of the form. Here, the special <code>template:multiple-choice-value</code> |
paulb@656 | 113 | attribute indicates that the <code>option</code> element maps onto a |
paulb@656 | 114 | <code>type-enum</code> element which is not mentioned in our revised |
paulb@656 | 115 | form data structure above; this will be discussed below.</li> |
paulb@141 | 116 | </ol> |
paulb@656 | 117 | |
paulb@141 | 118 | <h2>Output Structures</h2> |
paulb@656 | 119 | |
paulb@141 | 120 | <p>Although we revised the form data structure above, and whilst the |
paulb@141 | 121 | revised structure can describe form data submitted by users of our |
paulb@141 | 122 | application, it is unfortunately not sufficient to define the form data |
paulb@141 | 123 | that is to be presented. Consider the multiple-choice values that shall |
paulb@141 | 124 | be presented to users: such values are not defined in our revised |
paulb@141 | 125 | structure. Therefore, we shall define an output form data structure as |
paulb@141 | 126 | follows:</p> |
paulb@656 | 127 | |
paulb@656 | 128 | <pre> |
paulb@656 | 129 | <?xml version="1.0"?> |
paulb@656 | 130 | <structure> |
paulb@656 | 131 | <item value="some value"> |
paulb@656 | 132 | <type value="some type"> |
paulb@656 | 133 | <type-enum value="choice #n"/> |
paulb@656 | 134 | </type> |
paulb@656 | 135 | <subitem subvalue="some other value"/> |
paulb@656 | 136 | </item> |
paulb@656 | 137 | </structure> |
paulb@656 | 138 | </pre> |
paulb@656 | 139 | |
paulb@148 | 140 | <h3>Presenting the Extra Values</h3> |
paulb@656 | 141 | |
paulb@615 | 142 | <p>In the template, the <code>option</code> element is presented |
paulb@148 | 143 | using a number of special annotations which make more sense when |
paulb@148 | 144 | considering the above output structure:</p> |
paulb@656 | 145 | |
paulb@148 | 146 | <ul> |
paulb@615 | 147 | <li>The <code>template:multiple-choice-value</code> annotation states that the |
paulb@615 | 148 | <code>option</code> element maps into the <code>type-enum</code> |
paulb@656 | 149 | element, meaning that each <code>type-enum</code> element will be |
paulb@656 | 150 | reproduced as an option inside the list or menu presented in the Web |
paulb@656 | 151 | form.</li> |
paulb@615 | 152 | <li>The <code>template:multiple-choice-value</code> annotation also states that the |
paulb@656 | 153 | contents of the <code>option</code> element will correspond to |
paulb@656 | 154 | the value of the <code>type-enum</code> element's <code>value</code> |
paulb@656 | 155 | attribute.</li> |
paulb@656 | 156 | <li>The <code>template:multiple-choice-value</code> annotation provides |
paulb@656 | 157 | a final piece of information: the name of an attribute which will be |
paulb@656 | 158 | created on the <code>option</code> element if the element's value |
paulb@656 | 159 | matches the enclosing <code>select</code> element's value. This has |
paulb@656 | 160 | the effect of making sure that the <code>select</code> element always |
paulb@656 | 161 | reveals the selected value in its list of values.</li> |
paulb@656 | 162 | <li>The <code>value</code> attribute is set to a value which does not |
paulb@656 | 163 | matter - it will be replaced in the final output.</li> |
paulb@656 | 164 | </ul> |
paulb@656 | 165 | |
paulb@615 | 166 | <p>The result of this is that the <code>type</code> element in the |
paulb@615 | 167 | this example structure fragment...</p> |
paulb@656 | 168 | |
paulb@656 | 169 | <pre> |
paulb@656 | 170 | <type value="2"> |
paulb@656 | 171 | <type-enum value="(Not selected)"/> |
paulb@656 | 172 | <type-enum value="Important"/> |
paulb@656 | 173 | <type-enum value="Not important"/> |
paulb@656 | 174 | <type-enum value="Personal"/> |
paulb@656 | 175 | </type> |
paulb@656 | 176 | </pre> |
paulb@656 | 177 | |
paulb@148 | 178 | <p>...is transformed into something resembling this HTML code:</p> |
paulb@656 | 179 | |
paulb@656 | 180 | <pre> |
paulb@656 | 181 | <select name="..."> |
paulb@656 | 182 | <option value="(Not selected)">(Not selected)</option> |
paulb@656 | 183 | <option value="Important" selected="selected">Important</option> |
paulb@656 | 184 | <option value="Not important">Not important</option> |
paulb@656 | 185 | <option value="Personal">Personal</option> |
paulb@656 | 186 | </select> |
paulb@656 | 187 | </pre> |
paulb@656 | 188 | |
paulb@148 | 189 | <p>Such presentation techniques are sufficient if the input form data |
paulb@148 | 190 | structure is identical to the output structure, but since we will |
paulb@148 | 191 | receive a structure resembling that defined |
paulb@148 | 192 | earlier (where the multiple-choice values are never sent back to the |
paulb@148 | 193 | application), yet need to present a structure like the one above, we |
paulb@148 | 194 | will |
paulb@141 | 195 | need to find a way of merging the range of allowed values into the |
paulb@141 | 196 | user-edited form data before presenting that data using our template.</p> |
paulb@656 | 197 | |
paulb@415 | 198 | <h2><a name="DocumentInitialisation"></a>Document Initialisation</h2> |
paulb@656 | 199 | |
paulb@148 | 200 | <p>There are many possible ways of inserting extra XML elements into an |
paulb@270 | 201 | existing XML document, but XSLForms provides an easy way of defining |
paulb@270 | 202 | lists of values that will be included in the way we desire. First, let |
paulb@270 | 203 | us define a |
paulb@148 | 204 | document containing all the possible values for the type field:</p> |
paulb@656 | 205 | |
paulb@656 | 206 | <pre> |
paulb@656 | 207 | <?xml version="1.0"?> |
paulb@656 | 208 | <type> |
paulb@656 | 209 | <type-enum value="(Not selected)"/> |
paulb@656 | 210 | <type-enum value="Important"/> |
paulb@656 | 211 | <type-enum value="Not important"/> |
paulb@656 | 212 | <type-enum value="Personal"/> |
paulb@656 | 213 | </type> |
paulb@656 | 214 | </pre> |
paulb@656 | 215 | |
paulb@615 | 216 | <p>We shall refer to this document when inserting the different <code>type-enum</code> |
paulb@148 | 217 | elements into our input form data structure to produce the output |
paulb@270 | 218 | structure described above; it can be |
paulb@148 | 219 | found in <code>examples/Common/VerySimple/Resources/structure_types.xml</code>.</p> |
paulb@656 | 220 | |
paulb@270 | 221 | <h3>Amending the Resource</h3> |
paulb@656 | 222 | |
paulb@270 | 223 | <p>To take advantage of this new information, it is necessary to |
paulb@270 | 224 | introduce some code into the Web resource to perform the document initialisation. The special WebStack resource that we <a href="Web-resource.html">subclassed earlier</a> provides some |
paulb@270 | 225 | convenient mechanisms for introducing XML documents and initialisations, and we |
paulb@148 | 226 | shall add a few extra attributes to our resource class in order to take |
paulb@148 | 227 | advantage of them:</p> |
paulb@656 | 228 | |
paulb@656 | 229 | <pre> # Under template_resources... |
paulb@656 | 230 | |
paulb@656 | 231 | init_resources = { |
paulb@656 | 232 | "structure" : ("structure_template.xhtml", "structure_input.xsl") |
paulb@656 | 233 | } |
paulb@656 | 234 | document_resources = { |
paulb@656 | 235 | "types" : "structure_types.xml" |
paulb@656 | 236 | }</pre> |
paulb@656 | 237 | |
paulb@148 | 238 | <p>These attributes define the following things:</p> |
paulb@656 | 239 | |
paulb@148 | 240 | <ol> |
paulb@270 | 241 | <li>A initialisation called <code>structure</code> which links |
paulb@656 | 242 | the <code>structure_template.xhtml</code> file (the template) |
paulb@656 | 243 | to the <code>structure_input.xsl</code> stylesheet file. This |
paulb@656 | 244 | is very similar to the way the <code>template_resources</code> |
paulb@656 | 245 | dictionary links templates to other stylesheet files producing |
paulb@656 | 246 | output.</li> |
paulb@615 | 247 | <li>A document referred to by the name <code>types</code> which |
paulb@656 | 248 | is provided by the <code>structure_types.xml</code> file.</li> |
paulb@148 | 249 | </ol> |
paulb@656 | 250 | |
paulb@270 | 251 | <p>To actually perform the initalisation or merge operation, we need to add a few extra |
paulb@615 | 252 | lines of code after the addition and deletion operations in the <code>respond_to_form</code> |
paulb@148 | 253 | method:</p> |
paulb@656 | 254 | |
paulb@656 | 255 | <pre> |
paulb@656 | 256 | # Under the addition and deletion operations... |
paulb@656 | 257 | |
paulb@656 | 258 | # Initialise the document, adding enumerations/ranges. |
paulb@656 | 259 | |
paulb@656 | 260 | structure_xsl = self.prepare_initialiser("structure") |
paulb@656 | 261 | types_xml = self.prepare_document("types") |
paulb@656 | 262 | structure = self.get_result([structure_xsl], structure, references={"type" : types_xml}) |
paulb@656 | 263 | |
paulb@656 | 264 | # Start the response. |
paulb@656 | 265 | </pre> |
paulb@656 | 266 | |
paulb@148 | 267 | <p>These lines do the following things:</p> |
paulb@656 | 268 | |
paulb@148 | 269 | <ol> |
paulb@615 | 270 | <li>Obtain the stylesheet for the <code>structure</code> initialisation.</li> |
paulb@615 | 271 | <li>Obtain the <code>types</code> document containing the |
paulb@656 | 272 | values to be merged into the form data.</li> |
paulb@615 | 273 | <li>Take the stylesheet and apply it to the form data, <code>structure</code>, |
paulb@656 | 274 | using a reference to the <code>types</code> document containing |
paulb@656 | 275 | the values.</li> |
paulb@148 | 276 | </ol> |
paulb@656 | 277 | |
paulb@615 | 278 | <p>The result of this should be a processed <code>structure</code> |
paulb@657 | 279 | document containing the type values for each <code>type-enum</code> |
paulb@657 | 280 | element in that document found under the <code>type</code> element |
paulb@657 | 281 | (as specified in the <code>template:multiple-choice-field</code> |
paulb@657 | 282 | attribute).</p> |
paulb@657 | 283 | |
paulb@657 | 284 | <h3>Specifying a Context Element</h3> |
paulb@657 | 285 | |
paulb@657 | 286 | <p>Note that the feature of <code>template:multiple-choice-field</code> |
paulb@657 | 287 | where the context element is specified as <code>-</code>, meaning the |
paulb@657 | 288 | element on which the attribute for the field will be found, has |
paulb@657 | 289 | implications for the naming of the root element in the document |
paulb@657 | 290 | providing the values for a multiple-choice field: such elements need |
paulb@657 | 291 | to be named after this context element, and it is frequently less |
paulb@657 | 292 | inconvenient (and more obvious) to explicitly state a context element |
paulb@657 | 293 | instead of adopting the name of the current element from the template. |
paulb@657 | 294 | One situation where the current element might be more convenient as |
paulb@657 | 295 | the context element is where many multiple-choice fields are to be |
paulb@657 | 296 | supplied by the same document containing each range of values for all |
paulb@657 | 297 | the different fields.</p> |
paulb@656 | 298 | |
paulb@148 | 299 | <h2>Other Multiple-Choice Data</h2> |
paulb@656 | 300 | |
paulb@148 | 301 | <p>We have now added a simple, single-valued multiple-choice field to |
paulb@270 | 302 | the application. However, many applications often need to obtain <a href="multivalue.html">multivalued multiple-choice data</a>, and this |
paulb@148 | 303 | kind of information is investigated in the next part of the development |
paulb@148 | 304 | <a href="overview.html">process</a>.</p> |
paulb@656 | 305 | |
paulb@656 | 306 | </body> |
paulb@656 | 307 | </html> |