This is the third in an ongoing series that examines the practical uses of XForms by building a todo list. In this tutorial we are going to build on part 1 (where we built our data model) and part 2 (where we refined the data model to support looping). In this tutorial we will cover ways of using binds and inline schemas to correctly type the data model and use correct input types.

We left of from tutorial 2, with a user interface that looked like this:

A nearly completed XForm to-do list

A nearly completed XForm to-do list

The problem with this is that we are required to enter dates and state whether the task is complete manually. What would be preferred is if we could use a checkbox or date picker. A naive approach is to edit the interface directly, and alter the Xforms input into a checkbox. Below, we have code that generates a XForms select option that presents a series of checkboxes, however since we are dealing with binary information, we only need one item to select from:

1
2
3
4
5
<xf:select ref="@complete" appearance="full" >  
    <xf:item>
         <xf:value>true</xf:value> 
    </xf:item>
</select>
A task list with tick boxes

A task list with tick boxes

But the problem with this is that if the true value isn’t selected, rather than the value be false, it will instead be empty. Additionally there is no “date input” input type, so we’d have to make a custom date picker. We could again hack how we evaluate this value, and make custom handlers for different datatypes, or… we could type our data correctly.

Using XForms Binds to provide data-typing

XForms is very data-driven in how it operates, and conforms very strongly to the Model-View-Controller design pattern. We have already covered to View – the HTML/XForms code presented to the user – and the Model – the data model that we have designed to describe the information we hope to capture – now its time to look at the Controller aspect of XForms, the XForms bind. Binds have a lot of uses, dictating the connections between the model and the view,  they can be used to compute values, control when certain inputs are available and they can be used to provide explicit data-typing for elements in the model.

To demonstrate this we will revert the insert into our xf:model some bindings for our data:

1
2
3
4
5
6
7
<xf:bind nodeset="//task/@complete" type="xs:boolean"/>
<xf:bind nodeset="//task/@dueDate" type="xs:date"/>
<xf:bind nodeset="//task" type="xs:string" readonly="./@complete=true()"/>
<!-- later -->
<td><xf:input ref="."/></td>
<td><xf:input ref="@complete"/></td>
<td><xf:input ref="@dueDate" /></td>

Here we have reverted our complete entry field to a simple input, but have declare it to be an XML boolean datatype, similarly we have declared the due date to be an XML date and the task name to be a string. We have also demonstrated the ability to disable content based on the binding by saying that a task can only be edited if it has been completed. The end result of this simple and declarative change is shown below:

A more completed task list

A more completed task list

The above image shows several changes have taken place:

  • The complete field now has a tick-box (not shown is the fact that this will store a true or false value without further scripting required)
  • The due date field has a button with ellipses (…) that when pressed shows a date selector.
  • Although subtle, the first task and due date are grayed out indicating it has been disabled. Similarly, the button that would drop down the date selector for the first task is now gone.

So far we now have a fairly complete user interface for managing our tasks. You can see the full code for the task list on Github, or view all past code in the same repository. In the next tutorial we’ll look at an alternate way of providing datatyping  by linking to or including inline XML schemas, which can be useful when the data structure is known ahead of time. Then we’ll look at defining submission methods so we can save our data with a web server.