- The problem:
Now that I have an easy way to generate record updates, what
if I had an equally easy way to generate the update form ?
- The solution:
It should be easy to create a function that uses a data format
similar to the update function but insted creates a form with
a series of input fields, possibly filled with the current record's
data, and the information to submit the new data and update the record.
The function should support some different type of input fields
(text and number fields, list, radio and checkboxes), and have
a way to silently pass more data (hidden fields).
- The original record:
<record><status>live</status><author>Mario</author><gender>male</gender><title>PHD</title><id>22</id><name>Luigi</name><password>secret</password><address>somewhere over the rainbow</address><phone>123-4567</phone><e-mail>luigi@somewhere.over.ra</e-mail><notes>this is a $dollar</notes></record>
- The form definition:
(
<field name="name" type="text">Name</field>
<field name="title" type="checkbox" values="MD PHD">Title</field>
<field name="gender" type="radio" values="male female">Gender</field>
<field name="password" type="password">Password</field>
<field name="e-mail" type="text">E-Mail</field>
<field name="phone" type="number">Phone</field>
<field name="status" type="enum" values="new live dead">Status</field>
)
- The update form:
- The "update-form" function:
define function update-form($root, $changes, $title)
{
let $input-fields :=
for $field in $changes
let $type := $field/@type
let $ele := $root/*[node-name(.) = $field/@name]
return
<div>
<span>{ $field/text() }</span>
{
if ($type = "enum")
then
<select>
{
for $option in tokenize($field/@values, "\s+")
return
<option value="{$option}">
{
if ($option = $ele/text())
then attribute selected { "true" }
else ()
}
{ $option }
</option>
}
</select>
else
if ($type = "radio" or $type = "checkbox")
then
for $value in tokenize($field/@values, "\s+")
return
<span>
<input type="{$type}" name="{$field/@name}" value="{$value}">
{
if ($value = $ele/text())
then attribute checked { "true" }
else ()
}
</input>
{ $value }
</span>
else
<input type="{ $type }" name="{ $field/@name }"
value="{ $ele/text() }"/>
}
</div>
let $change-elems := for $n in $changes/@name
return $root/*[node-name(.) = $n]
let $hidden-fields :=
for $ele in $root/* except $change-elems
return
<input type="hidden" name="{node-name($ele)}" value="{$ele}"/>
return
<form>
{ $input-fields }
{ $hidden-fields }
<input type="submit"/> <input type="reset"/>
</form>
}
- The disclaimer:
This version of the function doesn't support all the form elements
and there is no way to specify the form action.
Also, attributes are not copied.
Not big things: one day I am going to complete it, but at least you get
the point.