Validation Conditions

https://www.youtube.com/watch?v=QDYzkVKHm40

 

Validation Conditions are used to require that a user enters a certain type of response. A simple example could be requiring that a date be in the future, all the way through writing complex expressions. These help guide users in their responses, leading to a better user experience and data quality.

 

Table of Contents:

General Design Guidance

Creating a validation condition for input-type questions can be very useful as a way to minimize the risk of users entering erroneous data.  However, you should keep the following in mind:

  • Validation conditions should always be accompanied by descriptive constraint messages that will clearly inform the user what they need to correct. You can also add audio to constraint messages. For example, you may want to put a limit on a birth date to make sure the user doesn't accidentally put a date in the future.  But if you don't put a constraint message the user may not understand why their answer was not accepted. This can be very frustrating for the user.

  • You want to be careful about your validation - if a user enters data in the field that doesn't fit your validation rule, this could prevent your app from being used. Make sure that your conditions are realistic and consider allowing an extra margin on your allowed values to permit extreme cases.

Basic Validation Conditions

Validation Conditions "check" responses to make sure they meet the constraints that you specify. Validation conditions work such that if the entered information does not meet the logic you specify, a flagged message pops up for the user and blocks them from proceeding to the next question.

  • For a basic validation condition you can use the Expression Builder.

  • Whenever you are referring to the value of the question to which you are adding the validation condition, you will see the question referred to as "."

  • Common components of a validation condition might be the use of = , >, and <. For example:

    • . > 8 (the response must be greater than 8)

    • . =! 0 (the response cannot be 0)

    • . > 1 and . < 10 (the response must be greater than 1 and also less than 10) 

  • Restricting the length of a numeric ID or text field you can use the function string-length() (for more information on functions see https://dimagi.atlassian.net/wiki/x/VTLKfw).

    • To require a specific length (example: 8 characters long): string-length(.) = 8. NOTE: This length count includes spaces. 

    • To restrict the length of a string to a range of characters (example: 7-9 characters long): string-length(.) >=7 and string-length(.) <=9

  • To validate a date relative to today's date you can use the function today():

    • Restrict a date entered so that it cannot be in the future (must be today or earlier): . <= today()

    • Restrict a date such that it must be within the previous 10 months (305 days): . > today() - 305 and . <= today()

  • To require the user to enter in a text entry question in a specific format, you can use various regex functions. 

    • Requires the first letter be capitalized, and all other letters be lowercase: regex(., "^[A-Z][a-z]+$")

If you want to create complex expressions please see the Advanced Validation Conditions section.

Validation Message

In the Validation Message field, enter the desired message that will pop up if the entered information does not meet your validation condition.  You can enter a different message for each language of your application.  If you do not specify a validation message the user will see a generic message like "The response is out of range." It is strongly recommended to always use a useful validation message.

Examples

This Validation makes sure that the date of birth is both in the past, and between the ages of 10 and 59. 

7de180f4-4b89-41e0-81db-b4b64ff05c0e.png

Advanced Validation Conditions

This page contains advanced information.

If you are looking for basic information on validation conditions please visit the Basic Validation Conditions section.

 Sometimes there are inputs which require not only a valid range (IE: between 96 and 105), but a specific number of significant figures (96.6, not 96.65 or 96) or other specific structure (A1234). To set this up, you can use a constraint in the Validation Condition section for a field with a Regular Expression.

To design and test your regular expressions, you can use this website: RegExr: Learn, Build, & Test RegEx

Here are some basic examples:

  • To restrict a text field to accept only letters (no numbers allowed):

    • regex(. ,'^[a-zA-Z]+$')  not allowing spaces

    • regex(. , '^[a-zA-Z\s]+$')  allowing spaces

  • To restrict a text field to accept only numbers (no letters allowed):

    • regex(. ,'^[0-9]+$')

  • To restrict a text field to accept an alphanumeric entry (letters and numbers, no spaces or other characters):

    • regex(. , '^[0-9A-Za-z]+$')


Considerations

  • It is important that the input type for this question be text, not number, integer, or decimal; therefore you should use the question type "Text" or "Numeric ID/Phone Number" (this question type is technically text with a numeric keyboard appearance). Numbers are represented and compared by their numeric value, so "65.00" and "65" are equivalent. 

  • These validation example often don't validate the actual size of the number at all. You can similarly restrict the values before the decimal sign in your expression using regular expressions, but remember that if it is difficult to express whether a value is valid, users may have a hard time entering the correct value.

  • It is possible to restrict the input range in a language that uses different Unicode characters, to do that you would input the range of Unicode characters for that language in the regex expression

regex.JPG

Examples 

Example 1: Require a specific number of significant figures

To require an input with an arbitrary size, but always with two significant figures, you can use the following:

Valid Inputs: 34.00, 4.32, 0.23

Invalid Inputs: 34, 0.0, 2.3, 34.2222

Enter into Validation Condition = regex(., '^[0-9]*\.[0-9][0-9]$' )

the two [0-9] elements at the end are the placeholders for the significant figure digits. You can add or remove more to manipulate the number of digits

Example 2: Require up to a specific number of significant figures

 If you want to specify that the expression can have up to two significant figures the expression is somewhat more complex:

Valid Inputs: 34.00, 4.32, 0.23, 34, 3.2

Invalid Inputs: 34.444, 34.0000, 23. (with nothing after the ".) 

Enter into Validation Condition = regex(., '^[0-9]*(\.[0-9][0-9]?)?$')

In this case, you can add additional significant figures by appending more [0-9]? elements after the final one

Example 3: Require certain types of significant figures

 If you want to specify that expression can end in either .0 or .5, the expression is again somewhat different:

Valid Inputs: 20.5, 100.0, 45.5

Invalid Inputs: 20, 20.2, 97.7

Enter into Validation Condition = regex(., '^[0-9]*\.(0|5)$' )

Example 4: Require a phone number to be entered in a specific format

 If you want your phone number to appear in the format 123-456-7890 you can use the following validation condition:

regex(., '^[0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$' )

or

regex(., '^[0-9]{3}-[0-9]{3}-[0-9]{4}$' )

Example 5: United Kingdom NHS Number

The United Kingdom NHS number is a 10 digit number (9 real, 1 check digit). Here's the expression syntax to validate it (assuming your Question ID is 'NHS_Number'):

11 - (substr(#form/NHS_Number, 0, 1) * 10 + substr(#form/NHS_Number, 1, 2) * 9 + substr(#form/NHS_Number, 2, 3) * 8 + substr(#form/NHS_Number, 3, 4) * 7 + substr(#form/NHS_Number, 4, 5) * 6 + substr(#form/NHS_Number, 5, 6) * 5 + substr(#form/NHS_Number, 6, 7) * 4 + substr(#form/NHS_Number, 7, 8) * 3 + substr(#form/NHS_Number, 8, 9) * 2) mod 11 = substr(#form/NHS_Number, 9, 10)

Specific Validation Condition Examples

Make a subset of questions required

Sometimes you may have a set of questions and want to require the user to answer a subset of them. However, you want each user to be able to choose their own subset. 

For example, imagine you have two questions

Question ID

Question Text

Question ID

Question Text

color

What is your favorite color?

food

What is your favorite food?

In this scenario you want the user to answer exactly one of these, though the user can answer either one.

Option 1: Add a Preceding Question

The simplest solution would be to add a question beforehand which asks:

Question ID

Question Text

Question ID

Question Text

#form/select-question

Which question do you want to answer?

  • What is your favorite color?

  • What is your favorite food?

This question would be required, and then you could use the display conditions to show exactly one question, which would also be required.

Option 2: Allow Users to See All Questions - Using a label as a validation condition

Sometimes you want the users to be able to see all of the possible questions before choosing which one to answer. Here is a way to do that:

  1. Put all of the Questions in a Question List Group (works on Android)

This will put all of the questions on the same page.

  1. Create a Label after the Questions, but still in the Question List Group

This label will be displayed when someone does not answer exactly one question.

  1. Set the Label's Display Condition

You will want the display condition to show the label when you don't answer exactly one of them. For example:

(#form/color != '' and #form/food != '') or (#form/color = '' and #form/food = '')

  1. Set the Label's Validation Condition

We want to treat the label like a validation condition so put a validation condition that can never be met. For example:

1=2

Set the label's validation message to be: "You must answer exactly one of the above questions."

Now when the user doesn't answer exactly one question they will see an error message which prevents them from going forward until they correct it.

Defining a Default Value

To define a default response to a question, use the "Default Data Value" field in the logic section of a question (for more information on using logic in CommCare visit https://dimagi.atlassian.net/wiki/x/WCvKfw). Set the Default Data Value for a question to be a case property of your choosing. Default Data Values also work for multi-select questions, if the value loaded into the multi-select question is a string of the Question ID's of the desired default responses, separated by spaces.

This functionality is useful, for example, if you want to have an Update Registration or Modify Registration form that defaults the response to a given question entered at registration. For example, if you have a registration form with a Multi-Select question to find out the occupation of a woman and during registration you check-marked three of the choices: farmer, seamstress, and hairdresser. The response to this question could be saved in the case property as 'farmer seamstress hairdresser'. If you default the question to that case property, 'farmer' 'seamstress' and 'hairdresser' will show up pre-checked.

App Email and Phone Number Input Guidance

There have been instances, where phone numbers or email addresses contain values that are not valid. This is because the input is a "Text" question without a Validation Condition or with a simple Validation Condition.  Fortunately, there is a solution. The app developer can use a regular expression to validate the input. 

Regular expressions are used frequently in Computer Science, but they are not something that you find in the real world. There is a nice article on the history and use of regular expressions at Regular expression. They are simply a sequence of characters that define a pattern. Sometimes, you will also see them referred to as "regex". While it's easy to say what regular expressions are, creating the sequence of characters can be tricky.

Here are two regular expressions:

  • ^([A-Za-z0-9!#$%&\*\+\-\/=?^`{|}~])+(\.?([\w!#$%&\*\+\-\/=?^`{|}~]))*@([A-Za-z0-9]+(\-+[A-Za-z0-9]+)*\.)+([A-Za-z0-9])+$(?!\n)

  • ^((\+\d{1,3}[\s.-]*)?\(?\d{2,3}\)?[\s.\/-]*)?\d{3}[\s.-]*\d{4,6}(\s+x\d+)*$

The first is a pattern that matches a valid email address. The second is a pattern that matches a valid phone number, although just glancing at these two sequences of characters you might be left wondering.

Typically, regular expressions are used in a function that takes two parameters; a string and the regular expression. The function returns TRUE if the string matches the pattern defined by the regular expression.

  • regex(., '^([A-Za-z0-9!#$%&\*\+\-\/=?^`{|}~])+(\.?([\w!#$%&\*\+\-\/=?^`{|}~]))*@([A-Za-z0-9]+(\-+[A-Za-z0-9]+)*\.)+([A-Za-z0-9])+$(?!\n)')

This function call takes two parameters; a dot referring to the current question input and the regular expression. 

Regular Expressions in CommCare Apps

The section on advanced validation discusses the use of regular expressions in CommCare Apps. In CommCare Apps the function regex takes two parameters; the string and the pattern, and returns TRUE or FALSE depending whether or not the string matches the pattern. This link leads to the regex function definition in the list of CommCare functions. To use regular expressions in a Commcare App the user needs to add a validation condition to a question. 

Validating Email Addresses in CommCare Apps with Regular Expressions

To Validate email addresses in CommCare with a regular expression, in the App Builder create a "Text" question for the email input as usual. In the Validation Condition under "Logic" of the "Text" question paste the function call below and add an appropriate validation message:

  • regex(., '^([A-Za-z0-9!#$%&\*\+\-\/=?^`{|}~])+(\.?([\w!#$%&\*\+\-\/=?^`{|}~]))*@([A-Za-z0-9]+(\-+[A-Za-z0-9]+)*\.)+([A-Za-z0-9])+$(?!\n)')

Types of email addresses match this Pattern

Email addresses have two main parts: the local-part and the domain.

Local-part can have:

  • uppercase and lowercase Latin letters A to Z and a to z

  • digits 0 to 9

  • printable characters !#$%&*+-/=?^_`{|}~ (minus single and double quotes)

  • dot ., as long as it's not the first character, last character, or consecutive to another dot

Domain can have:

  • uppercase and lowercase Latin letters A to Z and a to z

  • digits 0 to 9

  • hyphen - , as long as it's not the first character, last character, or consecutive to another hyphen

Email addresses with the following will not match the Pattern, even though addresses with these characteristics may be considered valid:

  • single quotes (')

  • double quotes (")

  • domain parts with dotless domains

This Regular Expression above does not limit the length of the email address entered. Per Simple Mail Transfer protocol, valid email addresses are constrained to no more than 64 characters for the local-part, plus the @ character, and no more than 255 characters for the domain part.

Example Email Addresses that match the Pattern

Example Email Addresses that do not match the Pattern

  • admin.aaa.com (No @ symbol)

  • info@clinica.com,co (Comma where there should be a dot)

  • user.help@homeedu (Single level domain name/dotless domain)

  • admin@ http://aaa.com (space between @ symbol and domain)

  • regular'email'@test.net (single quotes)

  • "regularemail"@test.net (double quotes)

  • welike🙂emojis@example.com (no icons)

  • "Not Provided" (Not an email address)

If you would like to test a specific Email Address you can use this regex101: build, test, and debug regex.

Validating Phone Numbers in CommCare Apps with Regular Expressions

To Validate phone numbers in CommCare with a regular expression, in the App Builder create a "Text" question for the phone numbers as usual. In the Validation Condition under "Logic" of the "Text" question paste the function call below and add an appropriate validation message:

  • regex(., '^((\+\d{1,3}[\s.-]*)?\(?\d{2,3}\)?[\s.\/-]*)?\d{3}[\s.-]*\d{4,6}(\s+x\d+)*$')

While this regular expression should match all domestic USA phone numbers, the format of international phone numbers is complex. Therefore, there may be some International phone numbers that do not match this pattern. If you find one please let us know, so we can update the regular expression.

Example Phone Numbers that match the Pattern

  • (919) 555 7862

  • +1 (919) 555 7862 x222

  • 555 7862

  • +57 301 6246123

Example Phone Numbers that do not match Pattern

  • 123456 (too short)

  • ++1 919 666 1234 (duplicate plus symbols)

  • 919 666 runs (cannot contain letters)

  • "Not Provided" (Not a phone number)

If you would like to test a specific phone number you can use this: regex101: build, test, and debug regex.