Generate multiple choice alternatives, based on the answers in a repeat

Very interesting question!

This is possible but as far as I know you will need to write the dynamic select one in raw XML. What I would do is create my form in XLSForm leaving that question aside, convert the form to XML and then modify the select one.

The general idea is to use an itemset that refers to your repeat in the select1. To build my example, I started with the XLSForm here. Then I replaced the definition of the select1 with:

<select1 ref="/select-one-from-repeats/people_select_one">
  <label>Select the relevant people:</label>
    <itemset nodeset="/select-one-from-repeats/people">
      <value ref="person_name"/>
      <label ref="person_name"/>
  </itemset>
</select1>

The full, functioning form: select-one-from-repeats.xml (1.8 KB)

Notice that both the value and the label use the name entered by the user. Depending on what analysis you intend to do on the resulting data, you could also consider using a calculate that gets the position in the repeat and use that as the value.

7 Likes

Thanks a lot.
I will try it
Best regards

Hi Anibal

I have looked at your example and attached is a sample file for the example you have just. so you can try it to see if it best solve your problem.

xlsform

diabetes.xlsx (46.8 KB)

survey

choice

i have limited the names that will be listed in which of them has diabetes to 5 names, you can add more by creating more calculations and increasing the index repeat number to the largest number you want. example indexed-repeat(${name}, ${people}, xxxxxxx)

please try this and let us know your feedback. hope this will solve your problem now.

Thanks
fabla2020@gmail.com

5 Likes

Thanks a lot
It works
Best regards

1 Like

Hello, i am new in odk.
Above answer work for me but displaying the person name are not limited. I need limited person. If i had only two person then other check box are empty and also it can be selected. Please help!!!!!

Thank you!!!!

please can you show the above in XLS form

Thank you Hélène for this wonderful solution. I tested it and it worked perfectly.
Is there another way to do this directly through XLS form other than editing the XML file afterwords?

Best,
M

Hello @Fabla. I am having the same problem. I used indexed_repeat to list answers from a single select question in a repeat into a new single select question outside the repeat but it is only piping in the value label rather than the exact wording. I am attaching what i have done and i'd be grateful if you help.Haiti V04_2_support.xlsx (19.2 KB)

@smbai, change your HC3 question type to a text instead of select one type. it will work for you

Hello, I tried the wonderfull solution Fabla suggested and that works very good!

But I would like to have the number of selected-multiple options in the selected-multiple restricted to only those names that where entered in the repeat. So if p1 and P2 and P3 where entered, i only want to have a multiple choice list of 3 names, not 5 names (of which the two last entries are empty).

So not

#1: Paul
#2: Peter
#3: Mary
#4:
#5:

But just

#1: Paul
#2: Peter
#3: Mary

So I want to restrict the number of choices in the multiple-choice list to the number of entries in the repeat.

In the case I have, the number of repeats is not known in advance.

Bart R

thank you @LN its best solution it will be great if we know how to write its xlsforms
or either how to replace actually I don't know that

As of pyxform v1.3.1 and XLSForm Online v1.3.1, it is now possible to create a select from a repeat. The documentation is available here. We expect this will be released in Central within the next 2 weeks. This new feature produces exactly the same result as the example XForms modification I shared.

Use it with question type select_one ${field_in_repeat} where ${field_in_repeat} is the field you want to use for your select options. Note that the same text used to display each choice will also be used as the value that you will see in the data used for analysis and that it may contain spaces. This functionality is currently only supported for select_one (not select_multiple).

Other select features such as choice_filter are supported. select-one-from-repeats is a working example.

3 Likes

This development is almost perfect for my needs, but not quite. I wonder if you could offer some advice. Considering the select-one-from-repeats example you linked above, I want to move the select_one ${person_name} question to within the repeat. My expected behaviour is that for each repeat, the list of choices in select_one would be populated by all the answers submitted in previous repeats.

At present when I try this in XLSForm Online I get the following error:

Error: ODK Validate Errors:
>> Something broke the parser. See above for a hint.
org.javarosa.xpath.XPathException: XPath evaluation: Parse error in XPath path: [..[./person_name != '']].

The following files failed validation:
${select-one-from-repeats}.xml

Result: Invalid

I understand that this behaviour would present a problem during the first repeat, as there would be no available choices, and this leads me onto a linked issue regarding the behaviour of "appearance" = autocomplete and search. Currently autocomplete won't allow manual entry of an option not in the list of choices, but I believe it should, following the way autocompletion systems work in various other places. If select_one allowed manual entry of an option not in the list of choices, the first repeat issue I described could be avoided.

You will need to filter out the current repeat iteration with a choice filter that looks like position() != current()/../pos where pos calculates the current repeat position.

Here's a quick sample form. Unfortunately it looks like there are some bugs in the form conversion. When I convert this, I get:

<itemset nodeset="..[position() != ./pos and animal_type != '']">

This doesn't make any sense. If I replace it with

<itemset nodeset="../../pet[position() != current()/../pos and animal_type != '']">

Then I get the result that I think you're looking for. select-one-from-repeat-in-repeat.xml (1.4 KB) is the XML.

If you want to play with this yourself, you can trick the form into converting by specifying a choice list for the select and omitting the choice_filter. Then you can replace the itemset with something patterned on what I've written above. I'll take a look at the pyxform issue.

3 Likes

Hi @LN,

Excellent work! Thanks.
Can XLS version of this xml form be possible for you to provide here? Would be grateful.

Stay safe!
Raj

Thanks so much for your help. I'm only just delving into adjusting the raw Xform .xml, so your advice is appreciated. I'm struggling with how I would adjust the nodeset reference when I have a form set up like this one: select-one-from-repeat-in-repeat-in-group.xls (25.5 KB) .

I thought the answer might be:

<itemset nodeset="/data/pet/pet_group[position() != current()/../../pos and ../animal_type != '']">

but I get this validation error:

org.javarosa.xform.parse.XFormParseException: <repeat> member's binding [/data/pet/pet_group] is within the scope of a <repeat> that is not its closest containing <repeat>!

As you can see, the questions in the repeat are wrapped in a group with "appearance" = field-list to allow them to display on the same page. I would ordinarily set the repeat to field-list as in your example, but my actual form is somewhat more complex and fails with multiple field-list groups, nested repeats and so on.

Many thanks.

@Raj_Pravat the documentation has an XLSForm example. There's another one linked from my post above. What @johngodlee is trying to do is not currently available in XLSForm.

This is also not currently supported by the pyxform implementation so you'll definitely need to edit the XML for the time being.

First, your pos expression needs to be adjusted. You want the position of the repeat so you'll need to use position(../../) from within the nested group. Your itemset declaration would look something like:

<itemset nodeset="/data/pet[position() != current()/../pos and pet_group/animal_type != '']">
    <value ref="pet_group/animal_type"/>
    <label ref="pet_group/animal_type"/>
</itemset>

The itemset is always built directly on a repeat, not on any nested groups. So you need to start with /data/pet. The group nesting is accounted for in the value and label reference declarations. Those say "once you've found the repeat instances to include, here's how you get the right field to use as value and label".

For the second part of the repeat matching test that filters out any repeats in which animal_type is empty, you also need to account for the nested group. So the expression needs to be pet_group/animal_type != ''.

Thank you for your help. Having you talk me through the XML really helps and my issue is now completely resolved. I hope that in some way our discussion will help with further development of the project.

2 Likes

I see that the follow up question seems restricted to select_one (i.e. of the household roster). Can this be done in some other way for select_multiple (I see above that select_multiple cannot be used in the way described)?

Hi, I am trying to replicate the same approach but instead of text I have select-one and it did not seem to work. I would appreciate some help.
Test.xlsx (70.9 KB)