Skip to content

Functions

These are the functions a Forms expression can call by name. A name that is not on this list is refused when you save. A function can also be written as helpers.len(...).

This list is written by hand against the evaluator’s list of built-in functions. Each example is run by tests/forms-docs-examples.php, so a function that changes behaviour fails the example.

FunctionGives
len(x)The number of entries in a list, or characters in a text. 0 for null.
sum(list)The total of the numbers in a list.
avg(...), min(...), max(...)The average, lowest and highest of the numbers given, or of the numbers in a list.
concat(...)The arguments joined as text, skipping blanks.
join(list, separator)The entries of a list joined with a separator, skipping blanks.
coalesce(...)The first argument that is not null.
is_empty(x)True when there is no answer.
match(value, /pattern/)True when the text matches the pattern.
today(), now()Today’s date and the current time.
format_date(date, format)A date as text.
contains_text(text, phrase)True when the phrase is in the text, ignoring case and spacing.
like_name(name, pattern)True when a file name fits a pattern with * and ?.
in_folder(path, folder)True when a path lies inside a folder.
{"answers": {"tags": ["a", "b", "c"], "scores": [10, 20, 30], "v": [2, 4, 9]}}
len(answers.tags) > 2
true
sum(answers.scores)
60
avg(answers.v)
5

avg, min and max skip blank entries and text that is not a number. If nothing is left they give null.

{"answers": {"v": [10, "abc", 20], "empty": [null, ""]}}
avg(answers.v)
15
min(answers.v, 7)
7
max(answers.empty)
null

concat and join skip null and "", so no stray separators appear when an optional question is blank.

{"answers": {"a": "Ada", "b": null, "c": "Lovelace", "v": ["a", null, "", "c"]}}
concat(answers.a, " ", answers.b, answers.c)
"Ada Lovelace"
join(answers.v, "-")
"a-c"
{"answers": {"name": "Ada", "zero": 0}}
coalesce(answers.nickname, answers.name, "Anon")
"Ada"
is_empty(answers.zero)
false

today() and now() read the clock of the form. format_date(value, format) takes a date answer or text such as 2026-07-15. With no value it formats now. The format uses these letters: yyyy, yy, MMMM, MMM, MM, M, dd, d, EEEE, EEE, HH, H, hh, h, mm, ss, a. A value that is not a date gives null.

{"_now": "2026-05-30T12:00:00.000Z", "answers": {"dob": "1990-07-15"}}
today()
"2026-05-30"
format_date(answers.dob, "dd/MM/yyyy")
"15/07/1990"

today() and now() give text, not a date, so date methods do not work on them. For date arithmetic use mash.date.today(), or parse the date first. See Date methods.

{"_now": "2026-07-10T12:00:00.000Z"}
mash.date.today().subDays(90).toDateString()
"2026-04-11"
today().subDays(90)
error: Unknown method: subDays

These three are for forms that look at file names, such as a filing form.

{"answers": {"t": "I N V O I C E", "n": "DN_001.pdf", "p": "Notes/2026/a.pdf"}}
contains_text(answers.t, "invoice")
true
like_name(answers.n, "dn_*.PDF")
true
in_folder(answers.p, "notes")
true

in_folder matches whole folder names, so Notes does not hold Notes archive/a.pdf.

nosuch(1)
error: Unknown function: nosuch