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.
| Function | Gives |
|---|---|
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. |
Counting and totals
Section titled “Counting and totals”{"answers": {"tags": ["a", "b", "c"], "scores": [10, 20, 30], "v": [2, 4, 9]}}len(answers.tags) > 2truesum(answers.scores)60avg(answers.v)5avg, 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)15min(answers.v, 7)7max(answers.empty)nullJoining text
Section titled “Joining text”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"Defaults and blanks
Section titled “Defaults and blanks”{"answers": {"name": "Ada", "zero": 0}}coalesce(answers.nickname, answers.name, "Anon")"Ada"is_empty(answers.zero)falsetoday() 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: subDaysMatching names and paths
Section titled “Matching names and paths”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")truelike_name(answers.n, "dn_*.PDF")truein_folder(answers.p, "notes")truein_folder matches whole folder names, so Notes does not hold Notes archive/a.pdf.
Calling a function that does not exist
Section titled “Calling a function that does not exist”nosuch(1)error: Unknown function: nosuch