Formulas in Knackly can be thought of as "named expressions": with a formula, you can do anything you can do in an expression, but you can attach it to a type and give it your own name so it can easily be reused across the apps you create. Formulas, like all expressions, involve a combination of functions, operators, literal values, filters, and identifiers referring to variables, templates or other formulas.
In a formula, you can reference variables, templates, or other formulas by name. For example, if you wanted a formula that calculated the total based on the price and quantity, the formula would look like:
Price * Quantity
Formulas may include parentheses () to change the order of operations:
(Apples + Oranges) / Guests
Note: operators and functions designated with this icon: indicate a standard function or operator that is built into JavaScript – in these cases, additional documentation and examples can easily be found elsewhere on the Internet.
Text operators, filters and functions
Text operators
Operator | Description | Examples |
+ | Concatenate text values into a single text value. To concatenate static text, surround it with double quotation marks. To concatenate double quotation marks, you need to use a backslash (\) as an escape character. Equivalent to the concat(text) function. | Name + " - " + Age => Jane - 28 "\""+ProductName+"\"" => "GreatProduct" |
[ ] | Extracts a single character from a text value. Equivalent to the charAt(number) function. | "John Smith"[0] => J |
Comparison operators (text specific usage)
Operator | Description | Examples |
== | Is equal to. Determines whether two text values are the same or not. Case sensitive comparison. | "yes" == "no" => false "yes"[0] == "y" => true |
!= | Not equal to. Determines whether two text values are different. Case sensitive comparison. | "yes" != "no" => true "yes"[0] != "y" => false |
< | Determines whether one text value precedes another in alphabetical order. Roughly corresponds to the localeCompare(text) function returning -1. | "ant" < "boy" => true "boy" < "ant" => false |
<= | Determines whether one text value precedes or matches another in alphabetical order. Roughly corresponds to the localeCompare(text) function returning either 0 or -1. | "ant" <= "ant" => true "ant" <= "boy" => true |
> | Determines whether one text value follows another in alphabetical order. Roughly corresponds to the localeCompare(text) function returning a positive 1. | "ant" > "boy" => false "boy" > "ant" => true |
>= | Determines whether one text value follows or matches another in alphabetical order. Roughly corresponds to the localeCompare(text) function returning either 0 or 1. | "ant" >= "ant" => true "ant" >= "boy" => false |
Text filters
Filter | Description | Examples |
upper | Makes a text value uppercase. Equivalent to the toUpperCase() function. | "Hello!"|upper => HELLO! |
lower | Makes a text value lowercase. Equivalent to the toLowerCase() function. | "Hello!"|lower => hello! |
initcap : forceLower | Capitalizes the first character in a text value and (optionally) makes the rest of the text lowercase. | "macDonald"|initcap => MacDonald "macDonald"|initcap:true => Macdonald |
titlecaps : forceLower | Capitalizes each word in a text value and (optionally) makes the rest of the text lowercase. | "marty mcFly"|titlecaps => Marty McFly "marty mcFly"|titlecaps:true => Marty Mcfly |
contains : textToFind | Determines if a text value contains another text value. The search is case sensitive. Equivalent to the includes(text) function. | "MacDonald"|contains:"Don" => true "MacDonald"|contains:"old" => false |
else : text | Tests whether a text value is empty, and if so, supplies an alternative text value. | ClientName|else:"client" => John ""|else:"client" => client |
Text "methods" and properties (advanced)
Method | Description | Examples |
textValue.charAt(number) | Extracts a single character from a text value at the position indicated by number. Equivalent to use of the [ ] operator. | "John Smith".charAt(5) => S |
textValue.charCodeAt(number) | Returns an integer between 0 and 65535 representing the UTF-16 code unit at the position indicated by number. | "ABC".charCodeAt(0) => 65 |
textValue.codePointAt(number) | Returns a non-negative integer that is the Unicode code point value at the position indicated by number. | "☃★♲".codePointAt(1) => 9733 |
textValue.concat(text1[, text2, …]) | Concatenates the text arguments onto the "calling" text value. To concatenate static text, surround it with double quotation marks. To concatenate double quotation marks, you need to use a backslash (\) as an escape character. Roughly equivalent to use of the + operator. | Name.concat(" – ", Age) => Bob - 43 "".concat("\"", ProductName, "\"") => "GreatProduct" |
textValue.endsWith(text) | Determines whether textValue ends with text. Case sensitive. | "brown fox".endsWith("fox") => true |
textValue.first(count) | Extract count characters from the beginning of textValue. | "quick brown fox".first(5) => quick |
textValue.includes(text[, startAt]) | Determines whether textValue contains a specific substring (text) or not. The search is case sensitive. If startAt is specified, it searches textValue only from that position onwards. Similar to the contains filter. | "quick fox".includes("ick") => true "quick ox".includes("ick",3) => false |
textValue.indexOf(text[, start]) | Finds an occurrence of text in textValue starting from an optional start position. (start is 0 by default.) If no occurrence of text is found, the result will be -1. The search is case sensitive. | "brown fox".indexOf("fox") => 6 "brown fox".indexOf("o", 3) => 7 |
textValue.last(count) | Extract count characters from the end of textValue. | "quick brown fox".last(3) => fox |
textValue.lastIndexOf(text[, start]) | Finds the last occurrence of text in textValue starting from an optional start position. (start is the full length of textValue by default.) If no occurrence of text is found, the result will be -1. The search is case sensitive. | "brown fox".lastIndexOf("o") => 7 "brown fox".lastIndexOf("o", 6) => 2 |
textValue.localeCompare(text) | Determines whether textValue comes before, or after, or is the same as, the given text string in sort order. | "ant".localeCompare("boy") => -1 => ant precedes boy "boy".localeCompare("boy") => 0 => no difference in sort order "boy".localeCompare("ant") => 1 => boy follows ant |
textValue.length | Returns the length in characters of a text value. | "quick brown fox".length => 15 |
textValue.padEnd(length[, padding]) | Pads textValue by appending a given padding string (repeated, if needed) so the resulting value reaches the given length. If padding is omitted, spaces are used by default. | "boy".padEnd(5, "y") => boyyy |
textValue.padStart(length[, padding]) | Pads textValue by prepending a given padding string (repeated, if needed) so the resulting value reaches the given length. If padding is omitted, spaces are used by default. | "hat?".padStart(7, "wh") => whwhat? |
textValue.repeat(count) | Causes textValue to be repeated count times. | "beep ".repeat(3) => beep beep beep |
textValue.replace(oldText, newText) | Replaces a single occurrence (within textValue) of oldText with newText. Comparison is case sensitive. | "how now".replace("ow", "at") => hat now |
textValue.replaceAll(oldText, newText) | Replaces all occurrences (within textValue) of oldText with newText. Comparison is case sensitive. | "big dig".replace("i", "o") => bog dog |
textValue.search(pattern) | Searches within textValue for a substring that matches pattern, and returns the position in the string (if found) or -1 (if not found). pattern is a text value containing a JavaScript regular expression, although RegExp flags (g, i, m, etc.) are not allowed. | "356".search("^[0-9]+$") => 0 "35a6".search("^[0-9]+$") => -1 |
textValue.slice(start[, end]) | Extracts the part of textValue that begins at start and ends before end. If start or end is negative, it counts backwards from the end of textValue rather than from the beginning. If end is omitted, the extracted value will go from start to the end of textValue. | "abcde".slice(1) => bcde "abcde".slice(1, 4) => bcd "abcde".slice(0, -2) => abc |
textValue.split([separator[, limit]]) | Turns a text value into a list of text values by splitting it at each instance of separator. If separator contains multiple characters, that entire character sequence must be found in order to split. If separator is omitted or does not occur in textValue, the returned list will contain only one item (textValue). If separator appears at the beginning or end of textValue, or both, the array begins, ends, or both begins and ends, respectively, with an empty text value. If separator is an empty text value (""), the result is a list of text values, each a single character of textValue. | "a/b/c".split("/") => [ "a", "b", "c" ] "Hello there world".split(" ", 3) => [ "Hello", "there", "" ] (Two spaces after "there" causes an empty text value in the list, and the limit of 3 caps the number of items returned.) |
textValue.startsWith(text) | Determines whether textValue starts with text. Case sensitive. | "brown fox".startsWith("fox") => false |
textValue.strip(characters, fromStart, fromEnd) | Strips any occurrences of the given characters from the start, the end, or both the start and end of textValue. If fromEnd is omitted, it defaults to true. If both fromStart and fromEnd are omitted, they both default to true. | "aaabccc".strip("ac") => b "aaabccc".strip("ac", false) => aaab "aaabccc".strip("ac", true, false) => bccc |
textValue.substr(start[, count]) | Extract a substring of count characters starting at start. If count is omitted, the extracted substring goes from start to the end of textValue. | "an old fox".substr(3,3) => old "an old fox".substr(3) => old fox |
textValue.substring(start[, end]) | Extract a substring beginning at position start and ending before position end. | "an old fox".substring(3,6) => old "an old fox".substring(3) => old fox |
textValue.toInt() | Parses textValue and returns an integer. | 2 * ("32".toInt()) => 64 |
textValue.toLowerCase() | Makes textValue lowercase. Equivalent to lower filter. | "Hello!".toLowerCase() => hello! |
textValue.toUpperCase() | Makes textValue uppercase. Equivalent to upper filter. | "Hello!".toUpperCase() => HELLO! |
textValue.trim() | Removes whitespace from both the beginning and end of textValue. Whitespace includes spaces, non-breaking spaces, tabs, and line termination characters. | " Hello world! ".trim() => Hello world! |
textValue.trimEnd() | Removes whitespace from the end of textValue. trimRight() is an alias to this method. |
|
textValue.trimStart() | Removes whitespace from the beginning of textValue. trimLeft() is an alias of this method. |
|
Text "helper" functions
Function | Description | Examples |
text.fromCharCode(num1[, num2, …]) | Returns a text value created from the specified sequence of UTF-16 code units. | text.fromCharCode(189, 43, 190, 61) => ½+¾= |
text.fromCodePoint(num1[, num2, …]) | Returns a text value created from the specified sequence of Unicode code points. | text.fromCodePoint(9731, 9733, 9842, 0x2F804) => ☃★♲你 |
Comparison operators (numbers and dates)
Operator | Description | Examples |
left == right | Determines whether any value is equal to another value. Special note: you must use two equals signs. In JavaScript, a single equals (=) is used to assign a value to a variable. Knackly does not support this syntax. | 2 == 2 => true |
left != right | Determines whether any value is not equal to another value. | 3 != 2 => true |
left < right | Determines whether one number value or date value is less than another. | 3 < 5 => true date.today < date.new(2020,1,1) |
left <= right | Determines whether one number value or date value is less than or equal to another. | 5 <= 5 => true |
left > right | Determines whether one number or date value is greater than another. |
|
left >= right | Determines whether one number or date value is greater than or equal to another |
|
Logical operators and functions
Logical operators
Operator | Description | Examples |
left && right | Logical AND: the && operator will return a "truthy" value only if both its operands are "truthy". If the left-hand operand is falsy, the result will be whatever the value of the left-hand operand is. If the left-hand operand is truthy, the result will be whatever the value of the right-hand operand is. | true && true => true Client && Client.Name => John Smith (if Client is non-null) "" && 5 => "" |
left || right | Logical OR: the || operator will return a "truthy" value if either of its operands are "truthy". If the left-hand operand is truthy, the result will be whatever the value of the left-hand operand is. If the left-hand operand is falsy, the result will be whatever the value of the right-hand operand is. | false || true => true false || false => false |
! operand | Logical NOT: the ! operator will return true if its single operand is falsy, or false if its operand is truthy. | !true => false !false => true !Client => false (if Client is answered) => true (if Client is null / not answered) |
condition ? value1 : value2 | Conditional operator: returns value1 if condition is truthy, otherwise it returns value2. Can be nested. | Simple example: Sales > 50 ? "Win" : "Lose" Nested and cleanly formatted: WaterTemp > 100 Testing for "answeredness": BirthDate |
Number operators, filters and functions
Number operators
Operator | Description | Examples |
+ | Add together two numeric values | Size + 2 |
- | Subtract two numeric values | Price - 3.00 |
* | Multiply two numeric values | Price * Quantity |
/ | Divide two numeric values | Price / NumPeople |
% | Returns the remainder after dividing the left operand by the right operand. | 10 % 3 => 1 NumPeople % NumTables |
Number filters
Filter | Description | Examples |
format:general[:negative[:zero]] | Formats a numeric value into text. You can optionally supply separate format strings for positive numbers, negative numbers, and zero. The first (general) format given will be used if the zero and/or negative format is omitted. Format strings are fully specified in numeral.js's documentation: In addition to those supported by numeral.js, Knackly also supports format strings "a" and "A" to get spreadsheet column-style numbering. | 10000|format:"0,0.00" => 10,000.00 -5.5 | format: "0 %" => -550 % 25 | format: "0000" => 0025 28 | format: "A" => AB |
cardinal | Spells out a cardinal number in words. | 123|cardinal => one hundred twenty-three |
ordinal | Spells out an ordinal number in words | 123|ordinal => one hundred twenty-third |
ordsuffix | Provides the appropriate ordinal abbreviation suffix (without the number itself). | the {[Day]}{[Day|ordsuffix]} of the month => the 22nd of the month |
else:text | Tests whether a number value is zero (falsy), and if so, supplies an alternative text value. | Child.Age | else:"not yet one" |
Mathematical "helper" functions
Function | Description | Examples |
math.abs(x) | Returns the absolute value of x. | math.abs(-5) => 5 |
math.cbrt(x) | Returns the cube root of x. |
|
math.ceil(x) | Returns the smallest integer greater than or equal to x. | math.ceil(1.01) => 2 math.ceil(-1.01) => -1 |
math.clz32(x) | Count leading zeros in 32-bit binary representation |
|
math.exp(power) | Computes Euler's number (e) to the specified power. | math.exp(1) => 2.71828 math.exp(3) => 20.08554 |
math.expm1(x) | Returns a number representing ex - 1 |
|
math.floor(x) | Returns the nearest integer that is less than or equal to the value. | math.floor(1.99) => 1 |
math.fround(x) |
|
|
math.hypot(value1[, value2, …]) | The square root of the sum of squares of the given arguments. |
|
math.imul(a, b) | C-like 32-bit multiplication of a and b |
|
math.log(x) | Natural logarithm (base e) of a given number |
|
math.log10(x) | Base 10 logarithm of a given number | math.log10(1000) => 3 |
math.log1p(x) | Natural logarithm (base 3) of 1 plus the given number |
|
math.log2(x) | Base 2 logarithm of a given number | math.log2(1024) => 10 |
math.max(value1[, value2, …]) | Returns the largest of the given numbers | math.max(Amount, 1000) |
math.min(value1[, value2, …]) | Returns the smallest of the given numbers | math.min(Amount, 0) |
math.pow(base, power) | Returns a n umber representing the given base raised to the given power (exponent). | math.pow(3, 3) => 27 math.pow(7, 0) => 1 |
math.random() | A floating-point pseudo-random number between 0 (inclusive) and 1 (exclusive). |
|
math.round(x) | The value of the given number (x) rounded to the nearest integer. If the fractional portion of the argument is greater than 0.5, the argument is rounded to the integer with the next higher absolute value. If it is less than 0.5, the argument is rounded to the integer with the lower absolute value. If the fractional portion is exactly 0.5, the argument is rounded to the next integer in the direction of +∞. | math.round(3.5, 0) => 4 math.round(3.4, 0) => 3 |
math.sign(x) | Returns either a positive or negative 1, depending on the sign of x. |
|
math.sqrt(x) | Square root of the given non-negative number | math.sqrt(100) => 10 |
math.trunc(x) | The integer part of the given number. Truncate towards zero. |
|
Mathematical constants (not super useful in document assembly)
Property | Description | Examples |
math.E | Euler's number | math.E => 2.71828 |
math.LN10 | Natural logarithm of 10 |
|
math.LN2 | Natural logarithm of 2 |
|
math.LOG10E | Base 10 logarithm of e |
|
math.LOG2E | Base 2 logarithm of e |
|
math.PI | Pi, or the ratio of the circumference of a circle to its diameter |
|
math.SQRT1_2 | The square root of ½ |
|
math.SQRT2 | The square root of 2 |
|
Trigonometry "helper" functions (not super useful in document assembly!)
Function | Description | Examples |
math.acos(x) | Arccosine (inverse cosine) | |
math.acosh(x) | Hyperbolic arccosine (inverse hyperbolic cosine) |
|
math.asin(x) | Arcsine (inverse sine) |
|
math.asinh(x) | Hyperbolic arcsine (inverse hyperbolic sine) |
|
math.atan(x) | Arctangent (inverse tangent) |
|
math.atan2(y, x) | 2-agrument arctangent (2-argument inverse tangent) the angle in the plane (in radians) between the positive x-axis and the ray from (0,0) to the point (x,y) |
|
math.atanh(x) | Hyperbolic arctangent (inverse hyperbolic tangent) |
|
math.cos(x) | Cosine |
|
math.cosh(x) | Hyperbolic cosine |
|
math.sin(x) | Sine |
|
math.sinh(x) | Hyperbolic sine |
|
math.tan(x) | Tangent |
|
math.tanh(x) | Hyperbolic tangent |
|
Financial "helper" functions
Function | Description | Examples |
finance.FV(rate, nper, pmt[, pv, type]) | Future value of an investment with periodic constant payments and a constant interest rate. rate: interest rate per period nper: number of periods for the lifetime of the annuity pmt: payment amount per period pv: present value of the annuity (if omitted, defaults to 0) type: whether payments made at start or end of each period 0 = payments at end of period (default) 1 = payments at start of period | Future value of an investment of $1,000 per month for a period of 5 years. The present value is 0, interest rate is 5% per year and payments are made at the end of each month: finance.FV(0.05/12, 5*12, -1000) => 68,006.08 Future value of an investment of $2,000 per quarter for a period of 4 years. The interest is 10% annually and payment are made at the start of the quarter: finance.FV(0.1/4, 4*4, -2000, 0, 1) => 39,729.46 |
finance.NPER(rate, pmt, pv[, fv, type]) | Number of periods |
|
finance.PMT(rate, nper, pv[, fv, type]) | Payment amount per period |
|
finance.PV(rate, nper, pmt[, fv, type]) | Present value of a loan or an investment, based on a constant interest rate. rate: interest rate per period nper: number of periods for the lifetime of the annuity pmt: payment amount per period fv: future value of the annuity (if omitted, defaults to 0) type: whether payments made at start or end of each period 0 = payments at end of period (default) 1 = payments at start of period | Present value of an annuity that pays $1,000 per month for a period of 5 years. The interest is 5% annually and payments are made at the end of the month. finance.PV(0.05/12, 5*12, 1000) => -52,990.71 Present value of an annuity of $2,000 per quarter for a period of 4 years. The interest is 10% per year and payments are made at the start of the quarter. finance.PV(0.1/4, 4*4, 2000, 0, 1) => -26,762.76 |
finance.RATE(nper, pmt, pv[, fv, type, guess]) | Interest rate per payment period |
|
Date filters and functions
Date filters
Filter | Description | Examples |
format:string | Formats a date value into text. Format strings are fully specified in date-fns' documentation: | => |
else:text |
|
=> |
Date "methods" (advanced)
Method | Description | Examples |
dateValue.getDate() | Extracts only the day (of the month) from dateValue. Equivalent to date.dayOf(). | NewYearsEve.getDate() => 31 |
dateValue.getDay() | Returns the day of the week for dateValue, where 0 represents Sunday and 6 represents Saturday. Equivalent to date.dayOfWeek(). | MemorialDay.getDay() => 1 |
dateValue.getFullYear() | Extracts only the year from dateValue. Equivalent to date.yearOf(). | KnacklyOrigin.getFullYear() => 2019 |
dateValue.getMonth() | Extracts only the month from dateValue. NOTE: This returns a zero-based month, where 0 is January, 1 is February, … and 11 is December. For 1-based months, either add one to the result, or see the date.monthOf() helper function. | ValentinesDay.getMonth() => 1 |
date1.isAfter(date2) | Tests whether date1 is after date2 chronologically. Equivalent to date1 > date2 (?) |
|
date1.isBefore(date2) | Tests whether date1 is before date2 chronologically. Equivalent to date1 < date2 (?) |
|
date1.isEqualTo(date2) | Tests whether date1 and date2 represent the same day. Equivalent to date1 == date2 (?) |
|
date1.isNotAfter(date2) | Tests whether date1 is NOT after date2 chronologically. In other words, date1 is no later than date2, or, date1 is before or on date2. Equivalent to date1 <= date2 (?) |
|
date1.isNotBefore(date2) | Tests whether date1 is NOT before date2 chronologically. In other words, date1 is no earlier than date2, or, date1 is on or after date2. Equivalent to date1 >= date2 (?) |
|
date1.isNotEqualTo(date2) | Tests whether date1 and date2 represent different days. Equivalent to date1 != date2 (?) |
|
dateValue.valueOf() | Returns an internal value representing the date, which is the number of milliseconds between 1 January 1970 and that date. |
|
Date "helper" functions
Function | Description | Examples |
date.addDays(dateValue, d) | Returns the date a specified number d days after dateValue. | date 10 days after openingDate: date.addDays(openingDate, 10) |
date.addMonths(dateValue, m) | Returns the date a specified number m months after dateValue. | date 3 months after startDate: date.addMonths(startDate, 3) |
date.addWeeks(dateValue, w) | Returns the date a specified number w weeks after dateValue. | date 8 weeks after startDate: date.addWeeks(startDate, 8) |
date.addYears(dateValue, y) | Returns the date a specified number y years after dateValue. | date 2 years after startDate: date.addYears(startDate, 2) |
date.age(dateValue) | Calculates the number of whole years between dateValue and today. | date.age(BirthDate) => 27 |
date.dayOf(dateValue) | Returns the day portion (day of the month) of dateValue in the form of a number between 1 and 31. Equivalent to dateValue.getDate() | date.dayOf(Christmas) => 25 |
date.dayOfWeek(dateValue) | Returns the day of the week for dateValue, where 0 represents Sunday and 6 represents Saturday. Equivalent to dateValue.getDay() |
|
date.daysBetween(date1, date2) | Returns the number of calendar days between date1 and date2. |
|
date.monthOf(dateValue) | Returns the month portion of dateValue as a number between 1 (January) and 12 (December). Note the difference in numbering with dateValue.getMonth() |
|
date.monthsBetween(date1, date2) | Returns the number of full months between date1 and date2. |
|
date.new(y, m, d) | Converts the given year, month (1-12) and day (1-31) numbers to a date value. |
|
date.parse(textValue) | Attempts to parse the given textValue as a date, returning the resulting date value. |
|
date.subDays(dateValue, d) | Returns the date a specified number d days before dateValue. | date 10 days before openingDate: date.subDays(openingDate, 10) |
date.subMonths(dateValue, m) | Returns the date a specified number m months before dateValue. | date 3 months before startDate: date.subMonths(startDate, 3) |
date.subWeeks(dateValue, w) | Returns the date a specified number w weeks before dateValue. | date 8 weeks before startDate: date.subWeeks(startDate, 8) |
date.subYears(dateValue, y) | Returns the date a specified number y years before dateValue. | date 2 years before startDate: date.subYears(startDate, 2) |
date.today() | Returns the current date in the local time zone. (Note that the results of this function changes only when the formula is recalculated. It does not update continuously.) |
|
date.yearOf(dateValue) | Returns the year portion of dateValue as a number between 1000 and 9999. |
|
date.yearsBetween(date1, date2) | Returns the number of full years between date1 and date2. |
|
True/false filters
Filter | Description | Examples |
format:iftrue:iffalse | "Format" a true/false value as one of the provided text arguments. Note: the conditional operator can do the same thing more concisely (coin ? "heads" : "tails"), so this is not very useful. | coin|format:"heads":"tails" => "heads" |
List properties, filters and functions
List properties
Property | Description | Examples |
length | The number of items in the list. | Children.length => 4 |
List operators
Operator | Description | Examples |
[ ] | Extracts a single item from a list, where 0 retrieves the first item, 1 retrieves the second item, and so on. | Children[0] => the first child in the Children list |
List filters
List filters provide a way to filter, sort, and otherwise manipulate lists of data.
Filter | Description | Examples |
any:expr | Produces a true/false value indicating whether the given expression (predicate) is true when evaluated against any item in the input list. The filter stops evaluating as soon as it finds one item in the list where the expression evaluates to a truthy value. This filter can also be used under the alias of some. | Do any children have a name that starts with C? Children|any:Name.startsWith("C") => true |
contains:value | Produces a true/false value indicating whether the given value exists in the input list. Equivalent to the includes function. | Does a list of text values contain a specific text value? TextList|contains:"this value" => false |
every:expr | Produces a true/false value indicating whether the given expression (predicate) is true when evaluated against EVERY item in the input list. The filter stops evaluating as soon as it finds one item in the list where the expression evaluates to a falsy value. This filter can also be used under the alias of all. | Are all the children married? Children|every:IsMarried => false |
filter:expr | Produces a filtered subset of the input list. The output list will contain every item from the input list where expr is true when evaluated against that item. | List all of the minor children: Children|filter: |
find:expr | Produces a single value of the same type as the items in the input list. The given expression is evaluated against each item in the input list (in order). The first item where expr is true (or truthy) gets returned as the result of the find. | Get the party designated as executor: Parties|find:Role=="Executor" |
group:expr | Produces a list of groups or categories from a flat input list. The given expression (expr) is evaluated against each item in the input list. An output group is created for each unique result of that evaluation. Each item in the output list (that is, each output group) is an object with two properties: _key: the result of evaluating expr _values: a list of the same type as the input list | List parties by relationship to the client: {[list AllParties|group: Client's {[_key]}s: {[list _values]} {[Name]} {[endlist]} {[endlist]}
|
map:expr | Produces a list of items where each item in the input list "maps" to exactly one item in the output list. The given expression (expr) is evaluated against each item in the input list, and the result of that evaluation is placed in the output list. | Produce a list of names (simple text values) from a list of children: Children|map:FullName
|
punc[:example] | Specifies a punctuation style for the list to which it is applied. Only has an effect when used in a {[list]} field in a template. Punctuation example strings consist of the digits (tokens) 1, 2, and optionally 3, separated by other characters as a way of indicating how items in this list should be joined together in text. If no example is provided, "1, 2, and 3" is assumed. Note: Unlike the rest of the list filters, this one outputs the same list that was passed into it. | {[list Children|punc]}{[Name]} {[endlist]} => John, Mary, Susan, and Edward {[list Boys|punc]}{[Name]} {[endlist]} => John and Edward {[list Children|punc:"1, 2."]}{[Name]} {[endlist]} => John, Mary, Susan, Edward. {[list Children|punc:"1, 2 and 3"]}{[Name]} {[endlist]} => John, Mary, Susan and Edward {[list Girls|punc:"1, 2, or 3?"]}{[Name]} {[endlist]} => Mary or Susan? |
reduce:reducer[:initial] | Produces a new value by evaluating the given reducer expression against each item in the input list. Typically follows one of two models: It can "reduce" the input list to a single value, such as when you want to calculate a value that requires some input from each item in the input list. Or it can "accumulate" a new list as it goes through each item in the input list. Items in this new list need not have a 1:1 correspondence with the input items. You can optionally specify an initial value for the output. For example, if the input list were empty, the output value would be whatever was specified as initial. If you do not specify an initial value, the first item in the input list becomes the initial value. Reducer expressions have access to a special local variable called _result., which is of the same type as either the initial value or the first item in the input list. _result is always set to the result of the previous item's evaluation. Think of _result as a kind of bridge between the evaluation of each item in the input. | Sum a list of numbers: NumberList|reduce:_result + this Do the same thing as the map filter, mapping a list of Children to a list of their names: Children|reduce:_result.concat( Do the same thing as the filter filter, conditionally adding items to the result only if the child's age is <18: Children|reduce: Flatten a nested list. Each child has a list of toys, and each toy has a ToyName, but we need a flat list of ALL the toy names: Children|reduce:
|
sort:key1[:key2…] | Changes the sort order of the list to which it is applied. Sort keys are expressions relative to each item in the list. Expressions will be evaluated for each item in the list, and the result is used to determine the order of the resulting list. | Specifying a sort with multiple keys: Parties|sort:LastName:FirstName Descending (reversed) sort order uses a minus sign: Matters|sort: -StartDate Sorting a list of text values (instead of objects): TextList|sort: this |
List "methods" (advanced)
Function | Description | Examples |
listValue.concat(item1[, item2…]) | Merges two or more lists. The concat method creates a list consisting of the items in the list on which it is called, followed in order by, for each argument, the items of that argument (if the argument is a list) or the argument itself (if the argument is not a list). | [1, 2, 3].concat(4, 5, [6, 7, 8]) => [1, 2, 3, 4, 5, 6, 7, 8] |
listValue.includes(item[, start]) | Determines whether a list includes a certain item among its entries, returning true or false as appropriate. If start is specified, it ignores any items in the list prior to that index. Equivalent to the contains filter. |
|
listValue.indexOf(item[, start]) | Returns the first index at which a given item can be found in the list, or -1 if it is not present. |
|
listValue.join([separator]) | Creates and returns a text value by concatenating all the items in a list of text values, separated by a specified separator value. If no separator is provided, an unspaced comma (",") will be used. If the list has only one text value, that value will be returned without using the separator. If the list contains items other than text values, they will be coerced to text and you'll probably get something ugly. |
|
listValue.lastIndexOf(item[, start]) | Returns the last index at which a given item can be found in the list, or -1 if it is not present. |
|
listValue.slice([begin[, end]]) | Extracts a portion of a list from begin (inclusive) to end (exclusive) where begin and end represent zero-based indices of items in the list. begin: Index at which to begin extraction. A negative index can be used, indicating an offset from the end of the list. If begin is omitted, slice begins from index 0. If begin is greater than the length of the list, an empty list is returned. end: Index before which to end extraction. A negative index can be used, indicating an offset from the end of the list. If end is omitted or is greater than the length of the list, slice extracts through the end of the list. |
|