Skip to main content

FEEL Function Reference

Forma uses FEEL (Friendly Enough Expression Language) for dynamic expressions. This page provides a complete reference of available functions and operators.

tip

Bookmark this page as a quick reference while building forms. Use the table of contents on the right to jump to specific functions.

Context Variables​

In FEEL expressions, you can access form data using these patterns:

PatternDescriptionExample
fieldNameDirect field accessage >= 18
computed.nameComputed field valuecomputed.bmi > 25
ref.pathReference data lookupref.taxRates.CA
valueCurrent field value (in validation)value >= 0
matrixField.rowIdMatrix row value (dot notation)service_rating.speed >= 3
item.fieldNameArray item field (in array context)item.quantity > 0
itemIndexArray item index (0-based)itemIndex = 0

Operators​

Arithmetic​

OperatorDescriptionExample
+Additionprice + tax
-Subtractiontotal - discount
*Multiplicationquantity * unitPrice
/Divisiontotal / count
**Exponentiationbase ** 2

Comparison​

OperatorDescriptionExample
=Equalstatus = "active"
!=Not equalstatus != "archived"
>Greater thanage > 18
>=Greater or equalage >= 21
<Less thanprice < 100
<=Less or equalprice <= 50

Logical​

OperatorDescriptionExample
andBoth conditions trueage >= 18 and hasLicense
orEither condition truestatus = "active" or status = "pending"
notNegationnot(isBlocked)

String Functions​

string length​

Returns the length of a string.

{
"rule": "string length(value) >= 3",
"message": "Must be at least 3 characters"
}

substring​

Extracts a portion of a string.

substring(string, start)
substring(string, start, length)
{
"expression": "substring(phone, 1, 3)"
}

Note: FEEL uses 1-based indexing for strings.

upper case / lower case​

Convert string case.

{
"expression": "upper case(code)",
"expression": "lower case(email)"
}

contains​

Check if a string contains a substring.

{
"visibleWhen": "contains(email, \"@company.com\")"
}

starts with / ends with​

Check string prefix or suffix.

{
"visibleWhen": "starts with(phone, \"+1\")"
}
{
"visibleWhen": "ends with(email, \".edu\")"
}

matches​

Test a string against a regular expression pattern.

{
"rule": "matches(value, \"^[A-Z]{2}[0-9]{4}$\")",
"message": "Must be 2 letters followed by 4 digits (e.g., AB1234)"
}

String Concatenation​

Use + to concatenate strings.

{
"expression": "firstName + \" \" + lastName"
}

Numeric Functions​

abs​

Returns the absolute value.

{
"expression": "abs(difference)"
}

floor / ceiling​

Round down or up to nearest integer.

{
"expression": "floor(price)",
"expression": "ceiling(quantity)"
}

round​

Round to specified precision.

round(number)
round(number, scale)
{
"expression": "round(total, 2)"
}

min / max​

Find minimum or maximum in a list.

{
"expression": "min([price1, price2, price3])",
"expression": "max([score1, score2])"
}

sum​

Sum all values in a list.

{
"expression": "sum([item1, item2, item3])"
}

mean​

Calculate the average of a list.

{
"expression": "mean([score1, score2, score3])"
}

Date Functions​

today​

Returns the current date.

{
"rule": "date(value) > today()",
"message": "Date must be in the future"
}

now​

Returns the current datetime.

{
"rule": "date and time(value) < now()",
"message": "Must be a past datetime"
}

date​

Parses a string into a date.

{
"expression": "date(dateOfBirth)",
"rule": "date(endDate) > date(startDate)"
}

Date Components​

Extract parts from a date.

{
"expression": "year(date(dateOfBirth))",
"expression": "month(date(startDate))",
"expression": "day(date(endDate))"
}

Date Arithmetic​

Subtract dates to get duration.

{
"expression": "date(endDate) - date(startDate)"
}

List Functions​

count​

Returns the number of items in a list.

{
"visibleWhen": "count(selectedItems) > 0"
}

all / any​

Check if all or any items match a condition.

{
"rule": "all items in items satisfy item.quantity > 0",
"message": "All items must have positive quantity"
}

append​

Add an item to a list.

{
"expression": "append(existingList, newItem)"
}

flatten​

Flatten nested lists.

{
"expression": "flatten([[1, 2], [3, 4]])"
}

Reference Data Functions​

get value​

Dynamic lookup in reference data using a field value as the key.

{
"referenceData": {
"taxRates": {
"CA": 0.0725,
"NY": 0.08,
"TX": 0.0625
}
},
"computed": {
"stateTax": {
"expression": "get value(ref.taxRates, state)"
}
}
}

Static Path Access​

For fixed paths, use dot notation.

{
"expression": "ref.constants.taxRate"
}

Nested Lookup​

Access nested properties from dynamic lookups.

{
"referenceData": {
"products": {
"SKU001": { "price": 9.99, "weight": 0.5 },
"SKU002": { "price": 19.99, "weight": 1.2 }
}
},
"computed": {
"productPrice": {
"expression": "get value(ref.products, selectedSku).price"
}
}
}

Conditional Expressions​

if-then-else​

Basic conditional.

{
"expression": "if age >= 18 then \"adult\" else \"minor\""
}

Chained conditions​

{
"expression": "if score >= 90 then \"A\" else if score >= 80 then \"B\" else if score >= 70 then \"C\" else \"F\""
}

Null Handling​

Null Check​

{
"visibleWhen": "email != null"
}

Safe Operations​

Handle null values with conditionals.

{
"expression": "if quantity != null then quantity * price else 0"
}

Null Coalescing​

{
"expression": "if discountRate = null then 0 else discountRate"
}

Common Patterns​

Age Calculation​

{
"expression": "year(today()) - year(date(dateOfBirth))"
}

Percentage Calculation​

{
"expression": "round((completed / total) * 100, 1)"
}

Conditional Discount​

{
"expression": "if subtotal >= 100 then subtotal * 0.9 else subtotal"
}

Status Based on Value​

{
"expression": "if computed.bmi < 18.5 then \"Underweight\" else if computed.bmi < 25 then \"Normal\" else if computed.bmi < 30 then \"Overweight\" else \"Obese\""
}

Expression Debugging​

If your expression isn't working as expected:

  1. Check field names - Ensure exact spelling match
  2. Verify data types - Numbers and strings behave differently
  3. Handle nulls - Unset fields return null
  4. Test incrementally - Start simple and add complexity

Common Errors​

ErrorCauseSolution
Expression returns nullField value is nullAdd null check
Type mismatchComparing number to stringUse consistent types
Field not foundTypo in field nameCheck field exists in schema
Syntax errorInvalid FEEL syntaxCheck quotes and operators