Form Display Conditions

Form Display Conditions—also known as Form Filtering or Form Display Logic—are used to filter the content of your CommCare application for a specific use case. Please see https://dimagi.atlassian.net/wiki/spaces/commcarepublic/pages/2143954971 for more information.

https://youtu.be/_6dC_9SGLyE?si=9AKe5inYgctEWMCl

When to use Form Display Conditions

Use Form Display Conditions when you have a form that you only want available to a specific group of users or cases. When you put a display condition on a form, it is only accessible on CommCare Mobile when a given user or case matches criteria you've previously defined.

For example:

  • you have a form that you want to be available only to certain types of users (in this workflow, you'll use user properties, rather than case properties, as your filter) 

  • you have a form that is only relevant to patients with a positive test result.

  • you have two versions of a form - one for children under one year of age, and one for all other children- and you want to make sure the user only chooses the correct form.

Setting Up Form Display Conditions

You first need to turn on the https://dimagi.atlassian.net/wiki/spaces/commcarepublic/pages/2143947412 for Display Conditions in your application. 

  • On the form's settings page, outside of the Form Builder, you can specify a display condition.  The display condition determines whether or not the form shows up in the form menu.  

  • You can view this field by selecting the button with three-bars in the top right hand corner and selecting to display the 'Logic' field

  • For this to work, the user must select the case BEFORE filling out the form.  This means that the "Menu Mode" setting on the module must be set to "Display module and then forms", and every form in the module must require a case.

  • It accepts the same kind of logical expressions as the Form Builder (see sections above), EXCEPT you must add ./ before any case property name. (For example, in Form Builder, you’d reference something as /data/edd. Here, it would simply be ./edd)

  • For example, write the following to say the expected delivery date (property name "edd") must be within the next week:  today() - ./edd <= 7

  • You can also refer to properties of some special cases too.

    • Use "#user" to refer to user case properties. e.g. #user/experience_level > 3

      • If a user does not have a value for the case property, you will see an error that says: "Logic references instance(commcaresession)/session/user/data/(...) which is not a valid question or value".

      • In order to avoid this, add an if() statement to check whether the case property exists first. For example:

        • if(count(instance('commcaresession')/session/user/data/USER_PROPERTY) > 0), instance('commcaresession')/session/user/data/USER_PROPERTY = 1, 0)

    • Use "#parent" to refer to the parent case of a child case. e.g. date(#parent/dob) >= date('1997-01-01')

    • Use "#host" to refer to the host case of an extension case. e.g. #host/suburb = #user/suburb

  • Referencing lookup tables on a form display condition uses a slightly different syntax than in app-builder. Here are some examples :

    •  instance('item-list:country')/country_list/country/id != "kenya"

    • instance('item-list:user_permissions')/user_permissions_list/user_permissions[user_role=#session/user/data/user_role]/f_register_household = '1')

Make Forms Disappear Once Filled Out

Sometimes you only want a form to be filled out one time for a case. The definitive way to do this is to use case management and form filtering, such that the form is only available until it has been filled out once.

First, you have to make sure that the form is in a module that only has forms that require a case. This means that there cannot be any registration forms in the module. That way the case list will display before the form list. Let's take an example where you have a Literacy Test form that you only want to fill out once for each of the pregnant women that you are monitoring in your app.

Set up the form:

  • In the Literacy Test form you will create a hidden value called something like literacy_form_complete

  • Set the calculate condition to be contain some text or number- for example, we could set the calculate condition to "complete"

  • In the form case management, save literacy_form_complete as a case property

Now you will need to set up a Form Display Condition for the Literacy Test form. Set the display condition so that the form only is displayed if literacy_form_complete DOES NOT equal complete. It would look like

./literacy_form_complete != 'complete' 

For each new case the literacy_form_complete property will be empty, so the form will be displayed. But whenever the Literacy Form is filled out for a case, the case property value will change to "complete" and the form's display condition will never be met.

Make Forms Appear in Sequence

Sometimes there are a number of different forms for a case and you want only one to be filled out at a time. You can set up an application so that at first it only shows "Home Visit 1" and then after that so it only shows "Home Visit 2," etc.

The basic structure is very similar to the instructions above for making a form disappear, and again this will only work in a module where all forms require a case (this allows the case list to show up before the form list)

Set up your forms:

  • In each form create a case property called next_form

  • Set the calculate condition in each form to be the name of the subsequent form you want to display, or a number for that form. For example, in Home Visit 1 the value of next_form will be "2" and in Home Visit 2 the value of next_form will be "3"

  • In the form case management make sure to save next_form as a case property in all forms

Set a Form Display Condition for each form that references the value of next_form. The display condition for Home Visit 1 would be ./next_form = '' or ./next_form = '1' (at first the case property next_form will be empty, and that is when we want to show Home Visit 1) and for Home Visit 2 it would be ./next_form = '2'.

To complicate this workflow a bit, suppose you have a form in the list that should only appear if certain conditions are met.  In that case, you can update the hidden value which updates the case property next form based on which form should appear next.  For example, let's say you only want display home visit 2 if the home being visited has a front yard, if not you'll want to skip firstly to the form Home Visit 3.  Your question (#form/front_yard) would be:

Does this home you're visiting have a front yard

a) 'yes'

b) 'no'

Then the hidden value which updates the case properties would then calculate to - #form/next_form = if(#case/front_yard = 'yes, '2', '3').

One thing to consider about these workflows is that they are very inflexible. So if for some reason a form needs to be filled out again, it is not going to be possible without having forms able to affect the next_form property in more complicated ways.

A solution to this is to have a 'reset forms' form which is always visible within the module.  This form can contain just one single-select question and each choice should correspond to a form in the list.  The value of each choice should correspond to the number of the form represented.

Eg - Which form would you like to reset to?

           a) Home Visit 1

           b) Home Visit 2

The value for choice a would be '1' and the value for choice b would be '2'.  The answer to this question should then update the case property next_form.

Impact on Data

Each form will have a unique form export available in the data export tab on CommCareHQ. Although you may be have multiple forms in an application, form filtering will hide these based on the display logic. As a result, form submissions will only display for the forms that were actually submitted.

For example – Let’s say you have three forms all named “Child Form”, but you use form filtering to divide this for children <1 year, 1-2 years, and 2-3 years. Although on the mobile it may appear as only on form, using form exports, this will display as 3 unique forms, and the form submission will display for its respective forms.