FS FormScript

The builtin library

FormScript gives you a library of functions, so most of what you need does not have to be written. There are 68 of them, and this page groups them by what they are for.

Converting

The call What it does
toString(v) the value as text
toNumber(v) the value as a number
toBoolean(v) the value as true or false
toDate(v) the value as a date

FormScript does not convert implicitly, so these are how you convert on purpose.

Asking what a value is

The call What it does
typeOf(v) the name of the type of the value
isEmpty(v) is it absent or empty?
isUnknown(v) is it unknown?
isInapplicable(v) is it inapplicable?
isAbsent(v) is it any kind of absence?
isKnown(v) is it a real value?

typeOf is how you ask a question about a type at runtime. It answers with the name of the type of the value, not of the type the document declares: one of string, integer, number, boolean, array, object, date, null or inapplicable. A decimal with no fractional part is an integer, a date literal is a string because a date is its own source text, and a value that could not be evaluated has no name at all — the error value propagates.

Text

The call What it does
len(s) the length in characters
graphemeLen(s) the length in grapheme clusters — what a person sees
lower(s) / upper(s) change the case
trim(s) remove the space at both ends
contains(s, t) does it contain it?
startsWith(s, t) / endsWith(s, t) does it begin or end with it?
replace(s, pattern, with) replace the matches
substring(s, from, to) part of the text
indexOf(s, t) where it is, or −1
split(s, separator) a list of pieces
join(list, separator) a list, joined back together
matches(s, pattern) does it match the pattern?
slugify(s) a URL-safe form of the text

len and graphemeLen are different on purpose. A flag emoji is one character to a person and several to a computer; graphemeLen is the one that matches what the reader sees.

slugify is NFKD, strips the accents, lowercases, and replaces every run of characters that are not a–z or 0–9 with a single -.

Numbers

The call What it does
abs(n) the absolute value
ceil(n) / floor(n) / round(n) round up, down, or to the nearest
min(a, b) / max(a, b) the smaller or the larger
avg(list) the mean
clamp(n, lo, hi) the value, held inside the range
pmt(rate, periods, principal) the level payment

pmt is the one that makes a loan form work:

forms-fragment
field monthly { type = number value = pmt(0.05 / 12, term, amount) }

It is the payment that pays the principal off over the number of periods, at the rate per period — which is why the rate is 0.05 / 12 and not 0.05.

Dates and times

The call What it does
now() the moment of the current transaction
today() the date of the current transaction
dateAdd(d, n, unit) n units later
dateDiff(a, b, unit) whole units from a to b
year(d) / month(d) / day(d) / weekday(d) the parts of a date
isBefore(a, b) / isAfter(a, b) ordering
age(d) the age of a person born on that date

The unit is one of "s", "m", "h", "d", "w", "mo", "y" — seconds, minutes, hours, days, weeks, months, years.

Months are clamped rather than overflowed: dateAdd(2026-01-31, 1, "mo") is 2026-02-28, not the 3rd of March. The specification says so, so that two runtimes cannot disagree about a birthday.

Lists

The call What it does
first(list) / last(list) the ends
sort(list) in order
unique(list) without the duplicates
flatten(list) one level deeper
take(list, n) / skip(list, n) a part of the list
minOf(list) / maxOf(list) the smallest or largest
count(list) how many
sum(list) the total
position() which element am I, inside a repeat

About the form itself

The call What it does
filledFields() the paths of the fields that hold an answer
isActive(path) is that field being asked?
isOverridden(path) was that field's answer replaced?
shadow(path) the value a field held before it stopped applying

These four read the state of the form rather than a value you pass them, and they are what a save-and-resume feature is written with.

Text and money in a language

The call What it does
t("key") the label for a key, in the current language
formatDate(d, pattern) a date, written out
formatMoney(n, currency) an amount of money, written out

About absence

The call What it does
coalesce(a, b, …) the first argument that is neither absent nor empty
ifNull(a, b) b if a is absent or empty
orDefault(a, b) b if a is absent
iif(cond, a, b) a if cond is true, b otherwise

These are in section 6, and they are the ones you will use most.

A rule about the list

The library is checked against the specification at build time. A builtin added to the specification without an implementation turns the build red, and a builtin implemented without being in the specification is a different kind of red. The list on this page is the whole list — there is nothing hidden behind an import.