Filter choice with values from the same repeat


I have a repeat group with a selec_one field. I'm trying to, according to the passt selected choices, filter the list for the next choices.
Ex. I have the following list:

In the first repeat I can chose any of them, but if I chose item '2', in the second iteration the list is presented as follows:
If now I chose item 1 the next iteration will just show the item '1':

Is there any way to do this using odk?

Welcome to the ODK forum, @ricardopmarinho ! We're glad you're here. When you get a chance, please introduce yourself on this forum thread.Thank you for adding a picture as your avatar; it helps build community!

Yes, what you ask is possible! Check out this thread (I think it answers your question):

Thanks for your reply, @danbjoseph.

Unfortunately the solution you showed don't solve my problem. In my case, I have to remove a possible choice from a list inside a repeat based on the previous choices at the same list.

To be clearer, I have a repeat group and a chose_one inside this group, for example, I have to chose between the numbers 1, 2, or 3.
If in the first iteraction I chose the number 2, when I go forward to the second iteraction, the same chose_one shouldn't have the number 2, just 1 and 3.

The thing is: I need to keep track of the previous choices in the same select_one to not show the ones I selected before.

Ah, apologies! I did not read your question closely enough. I can try and dig into this more later. Have you seen the documentation section on Repeat Recipes and Tips?

No problem. I've already seen this documentation part and couldn't find something to solve my issue.

Are you sure? It would be a little complicated but if you use choice filters functionality based on calculations including the indexed-repeat and position() function you could include, inside the repeat group, a calculation which calculates the previous answer. This answer could then be used to filter the choice list in the next round of the repeat. This is assuming that you know the maximum number of times the repeat count could run. If there is no limit to the repeat group, in theory it would still be possible but it would become more complicated again.

I've tried this but, for some reason, when I try to retrieve the value from past iterations at the same field, I can't make the form available for use.

This repeat have 15 iterations and 15 choices and I must know the value of each iteration to filter-choice.

My code was something like this:

begin_repeat | rep_group
select_one opt | opt_field | not(selected(indexed-repeat(${opt_field},${rep_group},position(..)-1)))

No it's not possible.

Can you confirm that its definitely not a "ranking" that you are creating as there seems to be some discussion on that topic recently?

I am not sure if the code you shared is a constraint or a choice filter but I dont think that would work as either: not(selected(indexed-repeat(${opt_field},${rep_group},position(..)-1)))

The selected function has two parameters. The first is a field name (not a calculation) and the second is a value from the choice lists. In your example there is only one parameter and its a calculation so I would guess it would not be possible to deploy like this.

The best may be to upload an xlsform or section of one and see if that makes things a little more clear.

sorry, it was soposed to be like this.


any way, if I try just the idexed-repeat like this (trying to get the previous value from the same field) it does not work

Is your form something you can share? Someone might have ideas about alternate ways to achieve the same thing.


form.xlsx (10.7 KB)

In this example I'm not trying to filter like I said, but already tryied to use the comand and didn't work

A post was split to a new topic: Filter options to remove previously selected choices

I came across this post while trying to do something very similar, and was able to identify a solution.

In a repeat loop, the choice_filter column can be used to filter out options selected in prior iterations of the repeat loop. This requires two pieces:

  1. A calculate filed added the line after end_repeat that joins the id's of the selected items.
  2. Using choice_filter to exclude items already selected.

For example,

type | name | label | calculation | choice_filter
begin_repeat | items | This is a loop | |
select_one item_select | item_id | Select Item | | not(selected(${id_join}, name))
end_repeat | | | |
calculate | id_join | | join(' ', ${item_id}) |

Hope that helps.

1 Like