Adding Cascading Selections in KoBoForm

 

Introduction

Cascading Selection, or itemsets, allows a KoBo user to create forms where a question's available options are filtered by a previous question's answer. For example, the first questions asks for a State, the second questions asks for a City in that State.

Details

Cascading questions

Cascading questions are primarily enabled by two Xforms elements, predicates and itemsets.

Itemsets allow a select or select1 element to use nodes from a data model instance as the options as opposed to a set of option elements. The nodeset attribute is used to set the instance and path to the set of nodes to use as options. The label and value elements in the itemset element are used to set which attributes in the nodes specified by the nodset attribute are to be used as the label(shown to the user) and value(stored in the database) of the select options.

Predicates are used to select which sets of the nodes specified by the nodeset attribute are shown to the user. Predicates can use the “@” to denote filtering by attribute. Thus if you had the attribute value in the nodes specified by the nodeset and you only wanted to select the ones with value 3 you would have a predicate of = 3?. Predicates can take in other nodes in the model for binary comparison operations. Thus you could filter the nodes by the value attribute given the value in the model at node “previous_question”, = /model/previous_question?. Predicates are what allows the itemset to dynamically select a set of values to show the user when looking at a select or select1 question.

It is possible for both the itemset data, and the data generated by the form to be stored in the same model, but this would cause all of the data, itemset data and form data, to be written to file. A better solution is to store the itemset data in a separate model instance from the form data. This way only the form data will be written to file when using an ODK collect client.

The “instance(<instance name>)” method is used to specify which instance to use if there is more than on instance in an xform. For example if the form data was stored in “myForm” and all the province and districts for a given country where stored in the “locales” instance a itemsets nodeset attribute for selecting a district could look like this: nodeset = “instance('locales')/locales/province= /myForm/province?/district”

The form builder now has a “Add Data” menu that allows the user to add new instances solely for storing data for itemsets and adding new elements to the data instances. The “Add Data Instance” button adds a new data model instance to the xform. The “Add Data Element” will add a new element to a data instance. By default the data elements contain a value and label attribute for storing the value saved in the database and the label shown to the user. However, you can use any attributes you wish. If a user wished to filter a set of elements by more than one criteria they could have as many attributes as needed to make such filtering possible.

The data instance properties view only allows the user to change the data instance id. This is the ID of the instance in the xform. This also changes the name of the root node in the data instance.

The data element properties view allows the user to set the name of the element. The name of the element must conform to XML rules and cannot have reserved characters, such as spaces. The properties view also lets the user add, edit, and remove attributes of the given data element.

To use an item set on a select or select1 question, in the question's properties view check the “Use Itemset” check box. The form builder will now show the item set as a child of the select or select1 question.

The itemset properties view allows the user to pick the data instance to use, the value attribute and label attribute to use, as well as the various levels and predicates into the item set. Due to limited development time, the form builder only supports one predicate per level. For example: nodeset: “instance('locales')/locales/province= /myForm/province?/district” as opposed to: nodeset: “instance('locales')/locales/province= /myForm/isNorthern?> /myForm/population?/district”

Also, due to limited development time, the form builder only support the equals binary comparison operator. The ODK collect client should support any binary comparision operator, for example, the form builder has no way to create the following, even though it will work in Collect: nodeset: “instance('locales')/locales/province> /myForm/population?/district”

When editing a itemset in the FB the user will need to keep in mind that there must be at least on “level” so the user has something to choose from. Each time there is more than one level, and the user wants to select only certain elements from the previous element, the use should add a predicate that filters based on the given attribute by another question in the form.

To expedite adding large sets of data the “Import CSV” feature which can be accessed by clicking on the “Import CSV” button. This will bring up a dialog that allows the user to paste in CSV data and a text box for specifying the name of the to be created data instance. The CSV should be in the format of

level_1_header,level_2_header,level_3_header,...,level_N_header
level1data,level2data,level3data,...,leveNdata
level1data,level2data,level3data,...,leveNdata
level1data,level2data,level3data,...,leveNdata
level1data,level2data,level3data,...,leveNdata

For example

Country,Province
USA,Alabama
USA,Alaska
Nigeria, Lagos State
Nigeria, Abuja

The header row, which is the first row, will be used as the name for the elements of different levels, and thus must conform to XML rules and not contain reserved characters (spaces, <, >, and such). The data in the following rows of the CSV file will be used as the label attribute of the elements created. The value attribute will be created automatically as a incrementing integer. For example in the above example of countries and provinces the following data instance would be created if I gave the intance the name “countries”

<instance id="countries">
        <countries>
          <Country label="USA" value="1">
            <Province label="Alabama" value="1"/>
            <Province label="Alaska" value="2"/>
          </Country>
          <Country label="Nigeria" value="2">
            <Province label=" Lagos State" value="3"/>
            <Province label=" Abuja" value="4"/>
          </Country>
        </countries>
      </instance>}}}

 

These details should be a lot of help, please visit KoBoForm online form builder and give it a try.