Complete Syntax Reference

IDEAL Survey maintains ODK compatibility while offering cleaner, more intuitive syntax.

Green rows indicate IDEAL-exclusive enhancements not available in standard ODK.

FeatureODK SyntaxIDEAL Syntax
Basic ref${question_name}{question_name}
Cross-surveypulldata('survey', 'field', 'id', 'value'){s1:question_name}
Repeat instanceindexed-repeat(${name}, ${family}, position(..)){family[0].name}
Last instanceindexed-repeat(${name}, ${family}, count(${family})){family[-1].name}
Current instance${name}{.name}
Countcount(${family}){family.count}
Sumsum(${items}/price){items[*].price.sum}
Averagesum(${items}/price) div count(${items}){items[*].price.avg}
Min/Maxmin(${items}/price){items[*].price.min}
Arithmetic${price} * ${quantity}{price} * {quantity}
Conditionalif(${age} >= 18, 'Adult', 'Minor'){age} >= 18 ? 'Adult' : 'Minor'
Complex calc(${baseline} - ${followup}) div ${baseline} * 100({baseline} - {followup}) / {baseline} * 100
Table cellNot supported{table_name[0].column_name}
Table columnNot supported{table_name[*].column_name}
Table last rowNot supported{table_name[-1].column_name}
Table col aggNot supported{table_name[*].column_name.avg}
Table row countNot supported{table_name.rows}
Cross-survey tableNot supported{survey_name:table_name[*].column_name.sum}
All instancesManual iteration{family[*].name}
Filter and aggComplex workarounds{family[age>18].income.avg}
Custom sepNot supported{family[*].name|join:"; "}
Text formatLimited{name|uppercase}
Number formatNot supported{score|number:2}
TruncateNot supported{text|truncate:50}
FallbackNot supported{q1 ?? 'N/A'}
Chained opsNot supported{score|number:2 ?? '0.00'}
Rich textLimited HTML**bold** *italic* __underline__ [color:blue]text[/color]

All Supported Functions

Note: Functions like round(), abs(), max(), min() and arithmetic operators are only available in Calculate question types. In regular question text, you can use formatters (|uppercase, |number:2) and aggregations (.sum, .avg) but not arithmetic operations.

CategoryFunctionDescriptionExample
Aggregate.sumAdd all values{items[*].price.sum}
.avgCalculate average{scores[*].value.avg}
.minFind minimum{prices[*].amount.min}
.maxFind maximum{scores[*].value.max}
.countCount instances{family.count}
Text Format|uppercaseConvert to uppercase{name|uppercase}
|lowercaseConvert to lowercase{name|lowercase}
|capitalizeCapitalize first letter{name|capitalize}
|trimRemove leading/trailing spaces{text|trim}
|truncate:NLimit to N characters with ...{text|truncate:50}
|join:"sep"Join array with custom separator{names|join:"; "}
Number Format|number:NFormat with N decimal places{score|number:2}
round()Round to nearest integerround({value})
abs()Absolute valueabs({diff})
max(a,b)Maximum of two valuesmax({a}, {b})
min(a,b)Minimum of two valuesmin({a}, {b})

Arithmetic Operations

Use standard arithmetic operators in Calculate question types to perform mathematical operations.

Addition: {a} + {b}
Subtraction: {total} - {discount}
Multiplication: {price} * {quantity}
Division: {total} / {count}

Comparison Operators

Use comparison operators in constraints and conditional logic to evaluate conditions.

Equals: === (e.g., {status} === "active")
Not equals: !== (e.g., {type} !== "draft")
Greater than: > (e.g., {age} > 18)
Greater or equal: >= (e.g., {score} >= 90)
Less than: < (e.g., {price} < 100)
Less or equal: <= (e.g., {quantity} <= 10)

Conditional Logic

Use ternary operators for conditional calculations in Calculate question types.

Basic ternary: {age} >= 18 ? 'Adult' : 'Minor'
With calculation: {age} >= 65 ? {price} * 0.8 : {price}
Nested conditions: {score} < 60 ? 'F' : {score} < 70 ? 'D' : 'C+'

Filtering Repeat Groups

Filter repeat group instances based on conditions before aggregating or displaying. This is an IDEAL-exclusive feature.

Filter by age: {family[age>=18].name} - Shows names of adults only
Filter by score: {students[grade>=90].name} - Shows high performers
Filter by category: {items[category==="food"].price.sum} - Sum food prices
Filter and aggregate: {family[age>18].income.avg} - Average adult income
Count filtered: {students[grade>=90].name.count} - Count A students

Practical Examples

Use CaseSyntax
Display previous answerYou entered: {name}
Calculate total price{price} * {quantity}
Sum all prices{items[*].price.sum}
Average income for adults{family[age>18].income.avg}
Format score with fallback{score|number:2 ?? '0.00'}
Reference previous surveyBaseline score: {baseline:total_score}
List names with custom separator{family[*].name|join:"; "}
Senior discount calculation{age} >= 65 ? {price} * 0.8 : {price}
Complex calculation example{weight} / (({height} / 100) * ({height} / 100)) | number:1