How is Constraint being used exactly?

I'm sorry for posting so many questions here on the forum.

Regarding select_one questions, Constraint:

not(selected(.,'B02'))

This 'constraint' will display an error when optionName B02 is selected.

This always happens when I am trying out validation on my forms. I am always confused on how Constraint really works.

Are conditions placed on contraint need to be what should not happen, or what should happen?

1. What is the problem? Be very detailed.

I have two select_one questions.
Q1 has 9 options
Q2 has 10 options

What I want to happen, is While Q1=opt 1-6 selected, and Q2=opt 2 selected, there would be an error.

2. What app or server are you using and on what device and operating system? Include version numbers.
I am using XLSForm Viewer to test the form: https://getodk.org/xlsform/

3. What you have you tried to fix the problem?
I have searched "Constraint on Select_one" on the net and this forum multiple times, but I have yet to find a solution to my problem.

  • I first tried isolating the conditions, from which When Q1 opt 1-6 is selected it would display an error

not(.='A00' or .='A01' or .='A02' or .='A03' or .='A04' or .='A05' or .='A06')

  • Then when Q2 opt 2 is selected, it would also display an error.

not(selected(.,'B02'))

  • I tried combining the two:

not(selected(.,'B02') and .='A00' or .='A01' or .='A02' or .='A03' or .='A04' or .='A05' or .='A06' )
But then Q2 doesnt display errors

  • Tried just separating them

not(selected(.,'B02')) and not(.='A00' or .='A01' or .='A02' or .='A03' or .='A04' or .='A05' or .='A06')
But then Q2 will always display error when opt 2 is selected.

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

ODK Tester (43).xlsx (39.0 KB)

Hi @Neko_Acedia

that's ok, it's always good to spend a few minutes googling and browsing the forum because I guess about 70% of new questions here are repeated but generally if you are not able to find anything helpful don't hesitate to ask.

according to the doc https://docs.getodk.org/form-logic/#validating-and-restricting-responses

To validate or restrict response values, use the constraint column. The constraint expression will be evaluated when the user advances to the next screen. If the expression evaluates to True, the form advances as usual. If False, the form does not advance and the constraint_message is displayed.

Yes and that's aligned with what's said in the doc If the expression evaluates to True, the form advances as usual`` not(selected(.,'B02')) will return false in such a case because selected(.,'B02') returns true and not() changes it into false.

regarding your problem... if you use constraints that calculate their result based on multiple questions like in your case it might be better to put those questions into field-list group to display on one screen. It's not a must I'm just mentioning it because I think in most cases it might make the form more readable.

To solve your problem you can use constraint like:
not((${op1}=’A01’ or ${op1}=’A02’ or ${op1}=’A03’ or ${op1}=’A04’ or ${op1}=’A05’ or ${op1}=’A06’) and .=’B02’)

Here is a corrected form:
ODK Tester (43).xlsx (7.4 KB)

The easiest way of thinking about constraints like that when you want to display it when a combination of different conditions take place is to build it in the way you naturally think about it and add not(), in your case such scenario you want to block is:

(${op1}=’A01’ or ${op1}=’A02’ or ${op1}=’A03’ or ${op1}=’A04’ or ${op1}=’A05’ or ${op1}=’A06’) and .=’B02’

and then just wrap it using not().

BTW. make sure that using constraints your questions require answer, otherwise if an answer might be empty constraints are not evaluated what might be confusing.

Thank you for the clear explanation for constraints, I was really confused as they work one way or the other at times mostly leading to an unexpected result that I never did understood.

Just to clarify, as I still did not understood how this code worked.

Was my mistake, where I placed .=’B02 first before (${op1}=’A01’ or ${op1}=’A02’ or ${op1}=’A03’ or ${op1}=’A04’ or ${op1}=’A05’ or ${op1}=’A06’) ?

No but I'm not sure which of options you provider you are referring now.

This one is generally ok but since you are using . (current question) that means you are in your first question and then you are just checking that particular part of your form. Your question was about checking answers from two questions at the same time (as a combination)

as above generally ok but you wanted to check both answers

so my constraint is a combination of those two:

not((${op1}=’A01’ or ${op1}=’A02’ or ${op1}=’A03’ or ${op1}=’A04’ or ${op1}=’A05’ or ${op1}=’A06’) and .=’B02’)

This one probably would work but you can't use dots everywhere. If you put that constraint in your second question you can use selected(.,'B02') but then instead of .='A00' you need ${op1}='A00'.

I see, I think I understand it now. Thank you, once again for the explanation.

I'll just add again because it was your mistake that dots in expressions like .='A00' you can use only if you refer an answer from the same question (the same row in xls form), but if you refer previous questions you need to add their full name like ${op1} for example. It applies to all calculations, constraints, relevant.