Validation

How validation (constraints) decides whether an entered answer is acceptable — rules, operators, messages, and examples

Validation decides whether an entered answer is acceptable. It runs after the respondent answers, and it can compare the answer to fixed values, to other questions in the survey, or to the results of functions.

Validation is not the same as:

  • Required — "the question must be answered at all". Required is a separate property on the question, not a validation expression.
  • Skip Logic — "the question is not shown". See Skip Logic.
  • Default Value / Calculation — "the answer is pre-filled or derived". See Default Values and Auto-Populate and Calculations.

Example: "Age must be at least 18":

${age} >= 18

Where to configure it

  1. Open your survey in the Survey Designer.
  2. Select the question in the canvas.
  3. In the right-hand Properties panel, scroll to the Advanced section.
  4. Click Validation Rules.

The Validation Rules dialog gives you two ways to work:

  • Visual rules — pick a rule type (Required, Minimum Length, Maximum Value, Pattern, and more), enter a value, and add a per-rule message. Rules are combined with AND (all must pass) or OR (any may pass) by clicking the connector badge between rules.
  • Custom Expression — the "Custom Expression" rule type accepts any valid expression, including cross-question and function-based constraints.

A Generated Constraint Expression preview updates as you build rules, and the expression is validated against the server when you save. You can also set a General Error Message that is shown when any validation fails; if it is left blank, the individual rule messages are used.

Note: note and calculate question types cannot have validation rules (the designer disables the save button for them).


Comparison operators

OperatorMeaningExamplePasses when
=equals= 'female'the value equals female
!=not equals!= 0the value is not 0
<less than< 18the value is under 18
<=less than or equal<= 65the value is 65 or less
>greater than> 18the value is over 18
>=greater than or equal>= 18the value is 18 or more

= is the equality operator. The web and mobile engines also accept == as an alias, but = is the canonical spelling — use it everywhere. There is no <> operator — use !=.

The dot . refers to the current question's value:

. >= 18

is the same as "this answer is at least 18". The visual rules generate .-based expressions, and the Constraint Explainer (the ? icon next to the question) can translate them back into plain-language descriptions.

Logical operators

OperatorMeaningExample
andboth must be true. >= 18 and . <= 65
orat least one true. = 0 or . = 1
not(...)negates the resultnot(. = 0)

Parentheses group conditions:

(. = 'yes' or . = 'maybe') and . != 'no'

Examples

Numeric range

Age between 18 and 65.

Business requirementOnly accept respondents aged 18–65
Expression. >= 18 and . <= 65
Passes whenthe answer is between 18 and 65 inclusive
Fails whenthe answer is below 18 or above 65
Suggested message"Age must be between 18 and 65"

Date range

Visit date cannot occur before the registration date.

Business requirementA follow-up visit must not be dated before enrolment
Expression${visit_date} >= ${registration_date}
Passes whenthe visit date is on or after the registration date
Fails whenthe visit date is earlier than the registration date
Suggested message"Visit date cannot be before registration date"

Date not in the future

Expression. <= today()
Passes whenthe date is today or earlier
Fails whenthe date is in the future
Suggested message"Date cannot be in the future"

Text length

Business requirementA code must be between 3 and 10 characters
Expressionstring-length(.) >= 3 and string-length(.) <= 10
Passes whenthe answer is 3–10 characters long
Fails whenthe answer is shorter than 3 or longer than 10
Suggested message"Code must be 3 to 10 characters"

The visual builder's Minimum Length and Maximum Length rules generate these expressions for you.

Regex / pattern

Business requirementPhone number must be exactly 10 digits
Expressionregex(., '^[0-9]{10}$')
Passes whenthe answer is exactly 10 digits
Fails whenthe answer contains anything else
Suggested message"Enter a 10-digit phone number"

The designer ships with built-in regex shortcuts — Email Format, 10-Digit Mobile, Numbers Only, Money (1 decimal), Letters Only, and Letters & Numbers — that expand to the full regex(., '...') expression automatically.

Selection validation (minimum selections)

Business requirementAt least two symptoms must be selected
Expressioncount-selected(${symptoms}) >= 2
Passes whentwo or more options in symptoms are selected
Fails whenfewer than two options are selected
Suggested message"Select at least two symptoms"

count-selected() counts the selected options of a select-multiple question. selected(${symptoms}, 'fever') checks whether one specific option is chosen.

Conditional validation

Business requirementIf the respondent is pregnant, the LMP (last menstrual period) date must be supplied
Expressionif(${pregnant} = 'yes', . != '', .)
Passes whennot pregnant, OR pregnant and a date was entered
Fails whenpregnant and no date was entered
Suggested message"Please provide the LMP date"

if(condition, thenValue, elseValue) evaluates the then value when the condition is true and the else value otherwise. Here, when the respondent is not pregnant the constraint is . — a bare non-empty value check — so it passes.

Cross-question validation

Business requirementEnd date must be after the start date
Expression${end_date} > ${start_date}
Passes whenthe end date is strictly after the start date
Fails whenthe end date is on or before the start date
Suggested message"End date must be after start date"

BMI validation

If a calculated BMI question exists, you can validate the input height and weight directly, or validate the computed result:

Expression (on weight). > 0 and . < 300
Expression (on height). > 0 and . < 250
Expression (on a calculated BMI)bmi(${weight_kg}, ${height_cm}) >= 16 and bmi(${weight_kg}, ${height_cm}) <= 40

Note that bmi() expects height in centimetres — see Auto-Populate and Calculations.

Required only under a condition

MQUAD's required flag applies unconditionally. To make a field required only when some condition holds, use if() as above:

if(${has_children} = 'yes', . != '', .)

When validation is evaluated

  • Web forms: simple constraints (comparisons like . >= 18, ${age} >= 18, and selected() / and / or / not() logic) are checked as you answer. Function-based constraints — string-length(.), regex(., ...), count-selected(...), date functions — are evaluated by the server at submission (they are not evaluated by the web client's inline checker).
  • Mobile field app: the full expression engine evaluates every constraint locally on each answer change and again at submission.
  • Form submission (both platforms): the server re-validates every constraint with the same expression engine, so a function-based constraint always fails submission on every platform even if the inline checker could not evaluate it.

Validation is skipped when the question has no answer — an empty value only fails if the question is Required. That means an empty answer does not fail count-selected(${symptoms}) >= 2; it fails only because the field is marked Required. Use if() to make a field required conditionally (see above).


Common mistakes

  • Using <> for not-equals — MQUAD uses !=; <> is not supported.
  • Forgetting the quotes — string values need quotes: = 'female', not = female.
  • Comparing a number to text — . >= '18' compares text, not numbers. Write . >= 18.
  • Putting the expression in the "Error Message" field — the message is plain text shown on failure, not an expression.
  • Using # references — ${name} is the correct reference style in constraints; #name is only for default values.