The art of hiding

30254
29
05-28-2016 02:27 AM
IsmaelChivite
Esri Notable Contributor
12 29 30.3K

This blog post is all about using the relevant column in your XLSForm to help you control the visibility of questionsSmaller.gif in your survey.  Mastering this is an important smart form design skill. A good smart form will never show end users a question unless it is necessary. The days where an endless collection of questions and data entry boxes are presented to the user should be over. The relevant column is present in the XLSForm survey worksheet and can optionally hold an expression. If the expression evaluates to true, the corresponding question will be shown. If the expression evaluates to false, it will be hidden. You can use data anywhere from your form as part of your expression, making your forms dynamically change based on the user's responses.

Lets go first through some examples:

Say you only want to ask a question if the response to a previous question is 'yes':

typenamelabelrelevant
select_one yes_noowner_presentIs the house owner present?
textowner_nameName:selected(${owner_name},'yes')

Other relevant expressions may include:

  • ${PreviousQuestion} < 18
  • int(${QuestionA})+ int(${QuestionB}) > 100
  • today() - ${LastInspectionDate} > 1000*60*60*24*15 (the last inspection happened more than 15 days ago)


The expression syntax uses the XLSForm specification. To learn more about how to write your own expressions check the Formulas—Survey123 for ArcGIS | Documentation help topic.

When using mathematical operators, one needs to be careful with empty responses. If a question has not been answered, it evaluates to 0. This would make for example ${PreviousQuestion} < 18 always return true, if ${PreviousQuestion} has not been answered.  To resolve this issue, you can add your expression to an if block as follows:

  • if (condition, a, b)  If the condition is met, returns a, otherwise returns b.
  • if(string-length(${PreviousQuestion}) = 0, false, ${PreviousQuestion} < 18)
  • if(string-length(${LastInspectionDate})=0, false, today() - ${LastInspectionDate} > 1000*60*60*24*15)

The safest way to check if a question has  been answered is using string-length(${QuestionName}).  If string-length returns 0, then you known the answer is empty. This function works well with question types of all sorts: with numbers, text, images, dates etc

In some cases, you may want to use regular expressions (regex) For example, the following expression can be used with a note type of question. If the expression evaluates to  true, the note is shown, otherwise it is hidden.

typenamelabelrelevant
textemailYour e-mail
noteType a correct e-mailregex(${Q2}, '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}')


A special case when using relevant statements are select_multiple questions. For them, the count-selected and selected statements are very handy. In the example below, the 'Select other topping:' question only appears if the choice 'Other' has been selected from the list of toppings.  The count-selected() function is used to display a 'Too many toppings' warning if more than 2 toppings have been selected.

typenamelabelrelevant
select_multiple toppingstoppingsPizza toppings
texttop_otherOther topping:selected(${toppings},'Other')
noteToo many toppings!count-selected(${toppings})>2

To learn more about select_multiple questions, have a look https://community.esri.com/groups/survey123/blog/2017/08/30/understanding-multiple-choice-questions-... 

Relevant expressions can be applied to many different types of questions: select_one, integer, text, image, barcode, repeat etc. You can also apply them to notes as well as to Groups and RepeatsGroups are of particular importance because a relevant statement applied to a Group will have effect over all questions within that Group.  If you have three or four questions to which you want to apply exactly the same relevant expression, you may want to consider creating a Group and apply the expression only to the Group. This will make your Survey load faster because you will be reducing the number of times the expression needs to be evaluated.

Another aspect to keep in mind is the effect relevant statements have on submit. If a question is not relevant (it is hidden), then data in that question will not be submitted to ArcGIS.

To learn more, check out the video tutorial below!


29 Comments
AndrewHargreaves
Occasional Contributor II

Hey @Ismael Chivite

How do I set a question to only appear if a previous question (of type select_one) is 'NOT BLANK' eg: the user has selected a value.

Thanks

IsmaelChivite
Esri Notable Contributor

${previousQuestion}!=''

CharlesBailey3
Occasional Contributor II

What if you wanted to evaluate multiple choices? I have tried something like selected(${multiSelect},'A,B') but doesn't work. 

JamesTedrick
Esri Esteemed Contributor

Hi Charles,

To do multiple, you need to group them in a compound statement:

selected(${multiSelect},'A') or selected(${multiSelect},'B')

CharlesBailey3
Occasional Contributor II

Thanks James, that works but it displays the relevant if 'A' or 'B' and any

other choices are selected. We's like it to specifically fire if 'A' or

'A,B' are selected, but no other combination. Is there a way to do that?

Having trouble getting an 'and' operator to work. Thanks again, cob

BrentKinal1
Occasional Contributor III

They're probably still having breakfast in Redlands, hope this helps:

Try: selected(${multiSelect},'A') or (selected(${multiSelect},'A') and selected(${multiSelect},'B'))

BrentKinal1
Occasional Contributor III

Ignore my previous post. After thinking about this again the relevant should probably look like this:

${multiSelect} = 'A' or ${multiSelect} ='A,B' or ${multiSelect} ='B,A'

The select multiple field populates in the order the options are selected so if 'B' was selected first the order of the answers would be "B,A". Knowing that users have a tendency to find exceptions to our logic I would add both permutations of an 'A,B' / 'B,A' combination.

JamesTedrick
Esri Esteemed Contributor

Update: I misread the requirement for evaluation, but will still keep this below to talk about negation

Brent's suggestion (which would also need or ${multiSelect} = 'B' ) is probably the shortest, unless there are sufficiently few choices that checking for the inverse (anything but A & B being selected) could also work (say we only have A,B,C,D as choices):

not(selected(${multiSelect}, 'C') or selected(${multiSelect}, 'D')) and count-selected(${multiSelect}) >= 1

CharlesBailey3
Occasional Contributor II

Brent, your second suggestion worked like a charm - what we needed was one

specific choice either by itself or in combination with one other specific

choice - this did the trick. Thanks, cob

ShawnRoberts1
Occasional Contributor

I'm fairly new to survey 123 so forgive me if this is an easy answer. 

I have 7 variables in a multiselect, call them A,B,C,D,E,F,G. i have a hidden text box that I would only like to appear if any combination of selections includes F or G. Example: A,B,C,F would make the textbox appear or  D,E,F,G. I really don't want to write out every combination, can you think of a way that I could do something like "multiselect includes F or G". 

Thanks,

ShawnRoberts1
Occasional Contributor

ended up answering my own question. I used a regEx. 

regex(${FIELD},'(F|G)') worked for me

MikeOnzay
Occasional Contributor III

It doesn't seem possible to evaluate different questions within the same relevant expression.

if((${Response}='Green Form'),True,if((${Leak_Response_Result}='Replaced'),True,False))

shows a text box when I first open the form. I thought that the False value would keep this box hidden unless one or the other previous questions were answered with the correct value.

While the above If statement passes the expression checker the following regex statement does not:

regex((${Response},'(Green Form)')|(${Leak_Response_Result},'(Replaced)'))

JamesTedrick
Esri Esteemed Contributor

Hi Mike,

The correct values for the if statements are true and false - note the lowercase.

Regex also would not be the best solution, as you're trying to match an exact value; to match one of two values you would need to use an or to join the separate comparisons:

${Response} = 'Green Form' or ${Leak_Response_Result} = 'Replaced'

KunikoChijiwa
New Contributor

Yes, it worked like a charm! Thank you.

joerodmey
MVP Alum

Is there an option to hide a repeat?

JordanMiller4
Occasional Contributor III

If I set up a field for dispatch how do I hide everything underneath until that dispatcher opens the form? Can it be done using a property("username")?

IsmaelChivite
Esri Notable Contributor

If you add property("username")='replacethiswithausername'  into the relevant field of a question, the question will only be shown when the indicated username is logged-in.

JordanMiller4
Occasional Contributor III

I'm having some issues using the property("username")='jnmiller@egas' multiple times for the relevant field. 

It works perfectly if I specify 1 user but as soon as I add more and use something like this it doesn't work: 

property("username")='jnmiller@egas' or property("username")='gkelly@egas

Maybe that function has a limit? Any ideas what could be causing this?

JamesTedrick
Esri Esteemed Contributor

Hi Jordan,

There shouldn't be a limit.  I am able to create a form with that pattern successfully:

BradWeir
New Contributor II

Been trying to find a solution to this problem for awhile. Thank you! I don't wan't to type out every single combination.

MichelleWilliams1
Occasional Contributor III

Following...

I have two repeats, and I'd like the relevant option to show.

If not, I'll use compact in the appearance field.

NeilJordan
New Contributor

James Tedrick I'm trying to set up a customized survey in the Conservation Easement Monitoring Solution.  I have two different surveys: one for easements and one for fee-owned properties.  Ideally the process would begin by selecting the property name, then based on the attribute "interest type" (easement or fee), the appropriate survey would be shown.  Any advice for a "conditional hide/show" type of formula based on the interest attribute?

Jelle_Stu_PR
Occasional Contributor II

I have a field that is always relevant but which I would like to hide (through 'hidden' in  the appearance column) under certain conditions. Is that also possible to achieve?

Courtney_Baldo
New Contributor

Just wondering if this is possible.  I am creating a form with cascading multiple choices questions for threats and when a threat is selected I have some hidden fields that ask for extra information.  It works when only one threat is selected but if I select a second threat,  the fields of the first threat get hidden again and does not display the hidden questions for the second threat unless all other threats are deselected.  

Basically what I want to do:

if threat 1 is selected , display extra questions

If threat 1 and threat 2 are selected, then display extra questions for threat 1 and 2

If threats 1,  2, 4, 8 and 12 are selected then display hidden questions for threat 1, 2, 4, 8 and threat 12

Currently I have the following expression in the relevant field and the hidden questions only display if only that individual threat is selected and nothing more:

For threat 1: ${Threatlevel2}='1.1_Housing_&_urban_areas'

For threat 2: ${Threatlevel2}='1.2_Commercial_&_industrial_areas'

MichelleWilliamsERM
Occasional Contributor III

Hello, Survey123 guru and Jedi!

I need help on my regex code.

I need the note to show up when the email is wrong, but it only shows up when it's correct so I added !=.

How do I make this correct?

regex(${OfficeEmail}!=, '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}')

MichelleWilliamsERM_1-1650298853484.png

 

 

 

ThomasHamill
Occasional Contributor II

@MichelleWilliamsERM, why not implement this as a constraint?

In the constraint column:
 regex(., '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}')

In the constraint_message column:
Type correct email

 

2022-04-18_144129.png2022-04-18_144156.png2022-04-18_144251.png2022-04-18_144308.png

jallen
by
New Contributor

Hi @IsmaelChivite and others!

I am creating a web app for lost pets using survey points from Survey123 collected from the public. I have two questions.

1) The likelihood of finding a pet after 5 days decreases by a large percent, so we want to be able to hide survey points after a certain amount of time so the public map app display is not clogged with old data. Is it possible to make survey points hidden after a certain amount of time?

2) I want to give people the option to share their contact info with the public or not. Regardless of what they choose, we still need their contact info. Is there a way to collect contact info and have it only display if they choose "yes" to share it, but if they choose "no" we can still collect and see it on the back end?

Thank you so much!

LiamHarrington-Missin
Occasional Contributor II

Hi @jallen,

Your message popped up and gave me a good opportunity to stop doing something boring.  

I think I would solve both questions by leveraging hosted feature views. 

For 1) I would ensure that the survey form includes a date field for "first observed missing".  Then I would create a feature view of the data that only shows the most recent (5 days) data based on that field.  That's the data I would share with the public

For 2) I would ensure that the survey has a share with public "yes/no" field and then create a hosted feature layer view for that contact only if that field is "yes".   I advise caution with this feature though as sharing contact info with the public is GDPR sensitive.  

https://doc.arcgis.com/en/arcgis-online/manage-data/create-hosted-views.htm

jallen
by
New Contributor

@LiamHarrington-Missin thank you for your response! I will give this a try