Recomputing calculated field in repeat group, after previous instance changed

Thanks, @Kal_Lam. Your answer brought me onto a good track.

After a day of experimentation, I now have a solution that works robustly and handles all the problems related to moving back and forth in the form. It also shows pretty nice error messages. I’d like to share the file here as an example for anyone who encounters similar problems in the future: Kobo Experiments.xlsx (9.0 KB)

A few explanations:

The form uses a required note field to display error messages when duplicates are detected. The note is displayed conditionally using its relevant field. This is different from the solution in the answer above, that use a constraint to prevent duplicates. It works better, because all global values are updated when the relevance is evaluated.

There are also other note fields that are not marked as required; these can serve as warnings. Warnings help the enumerator find places where they can correct something. Here’s how it looks in Enketo:

Later in the form, there is a section on nets (bednets protecting people from mosquitoes). This uses the new “select one from repeat” feature. Each net covers a certain number of people, and validation rules prevent the same person from being covered twice. For example:

As a bonus, the error message tells the enumerator the number of the net where the person has been used before. There’s some clever awful string manipulation to extract that position.

After each net, a summary shows which people have already been covered and which ones are outstanding. Unfortunately, this only works in Collect, not in Enketo:

The core ideas that make this possible:

  • Use a global variable all_selected that joins together all the selected elements.
  • Check if a value appears twice in this variable, by checking whether substring-before(all_selected, value) contains value,
  • For the summary, generate lists of not yet selected elements using something like join(', ', /data/person/person_name[not(contains(${all_selected}, .))])

Hope this is helpful!