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

What is the problem? Please be detailed.
I need to generate a multiple choice question (i will call it Q2), based on a previous question (Q1), Q1 asks the names of the people in the family, and my goal is that later, when i ask whom of them has a health problem, the choices be restricted to these people.
Is it possible

What ODK tool and version are you using? And on what device and operating system version?
We are using ODK Aggregate v1.4.15 windows-installer.exe, and writing on XLSForm

What steps can we take to reproduce the problem?
Just trying to write something with that concept:
To generate the choices from the answers from the answers of a previous one (ie.
Q1: Please, tell me the names of the people living at this house

  • Paul
  • Peter
  • Mary
  • Jane
    Q2: Check which of the people living here have Diabetes?

O Paul
O Peter
O Mary
O Jane

What you have you tried to fix the problem?
Just wrote using $, {var}, =, in several ways, both, in survey and in choices

Anything else we should know or have? If you have a test form or screenshots or logs, attach here.

Hello, if I understand you want that a question appear base on the response of Q1. If yes, try to use selected(${Q1}, 'XXX') where yous replace XXX by the name you want.
If i'm not not answering, pleas send a part of your xls form.

Thanks for the answer
My problem is that each family will answer different things (both, names and number of people).
I want the form to take the answer that they give, listing the family members, to generate the choices that the respondant has to answer a following question
I mean, in the question about the people having a disease in the family, each of them get the options according to the answer to the listing. This listing comes from a repeat, with an n generated from Q0
Something like: "take the name from Q1((asking for the names of the members of the family, and generate the choices for Q2 (select_multiple)
Q0 = How many people live here (integer/ name: num_fam )
Q1= Which are the names of them: (begin repeat /text/... repeat count: ${num_fam}
Here, I get one occurence (column) for each person [in reality, we ask some things about each of them, but it is not relevant for the problem]
Q2: Which of them has diabetes?
And here i would be the happiest of the Form-Writers if i can set it so that the choices here are not standardized for all, but they take the answer(s) to Q1, and transform them in a customised set of choices.
The form is in Spanish, Maybe it wouldn't be so helpful
Regards

1 Like

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 != ''.