Platio Expressions

Sometimes you might want to do some simple calculations while creating your MiniApp.

Platio Expression is a mechanism to do these kinds of calculations. Note that even though Platio Expressions look like JavaScript, you cannot use all features of JavaScript.

Examples

Let’s see some examples.

Calculation Field

You can specify an expression to Value property of a Calculation field.

You have Unit Price (Number), Amount (Number) and Total (Calculation) fields. Multiplication of the Unit Price and Amount will be set to the Total field when you specify c9dda012 * c48fdfa4 to Value property of the Total field where c9dda012 and c48fdfa4 are column IDs of the Unit Price and Amount fields.

Text Generation Field

You can specify an expression to Value property of a Text Generation field as well.

You have Family Name (Text), Given Name (Text) and Full Name (Text Generation) fields. A full name will be set to the Full Name field when you specify c42b023c + " " + c14d3611 to Value property of the Full Name field where c14d3611 and c42b023c are column IDs of the Family Name and Given Name fields.

Transform of Webhooks

A record will be sent to a server in the fixed JSON form as explained in Webhooks Programming Guide when you send it to an external server. However, you need to convert it to another JSON form when you want to send it directly to another service. You can do this by using Platio Expressions.

For example, let’s think about connecting to a server that accepts a request in the format below.

{
  "subject": "<Put a subject here>",
  "body": "<Put a body here>"
}

You can put values specified at Subject and Body field to subject and body using the expression below. Note that cff8e7af and c80c825e are column IDs of Subject and Body fields respectively.

{
  "subject": cff8e7af,
  "body": c80c825e
}

Condition of Webhooks

You can send a request to a server only when a record satisfies a certain condition.

For example, when you specify c978eb40 > 40 as a condition, a request will be sent only when a value of the Temperature field is greater than 40 degrees. Note that c978eb40 is a column ID of the Temperature field.

Complex Calculation Field

Let’s take a little bit complex Calculation field as another example. There is a Multiple Text Selection field to select an item with its price. Each value of this field is like Item A ($10), Item B ($5), Item C ($8). To set a total price of the selected items to a Calculation field, you can use the expression below. Note that c0be75a4 is a column ID of the Multiple Text Selection field.

sum(map(c0be75a4, value => number(replace(value, /.*\(\$(\d+)\)$/, "$1"))))

Parameters

You can use some parameters that are passed when an expression is evaluated. We use column IDs in the examples above, and these are parameters.

Parameters whose name is a column ID are passed when you use an expression to calculate a field value or convert and filter Webhooks. Each value is a value converted from the original value for the column. In addition to them, a parameter named record is passed. The value of this parameter is a JSON representation of a record.

Let’s take a record with a Text field and Multiple Number Selection field as an example. Column IDs of these fields are c63ae565 and c00bb867. Three parameters are passed in this case.

As you can see, you can refer to values in forms you can easily handle by using parameters named based on column IDs. You can use c00bb867[1] instead of record.values.c00bb867.value[1].value, for example. Usually you will use c63ae565 and c00bb867, but you can also use record if you want to use other information.

Use . to refer to a value in nested objects like this example. Also use 0-based index in [] to refer to an element in an array.

You can find how a value in a record is converted to a parameter in Types and Values.

Also, see Platio API Reference for the format of record parameter. You can find details of values in a record in Types and Values.

Parameters without values

It returns a default value of the type if no value is specified when you refer to a parameter by a column ID. For example, you’ll get an empty string if no value is specified for a Text field, and 0 for a Number field.

You can find a default value for each type in Types and Values.

References

Types

You can use these types in Platio Expressions. Values each type can have are the same as JavaScript.

All values appearing in an expression will be of one of these types, null or undefined.

Literals

These types have literals.

String

The syntax of an array literal is the same as Javascript, but you can only use double-quotes. Single-quotes are not supported. Escape special characters in a string literal in the same way as JavaScript.

Number

You can use a decimal number. Using exponential like 1e10 is not supported.

Boolean

The syntax of a boolean literal is the same as Javascript.

Date

There is no literal for Date.

Array

The syntax of an array literal is the same as Javascript. You can use a spread operator.

Object

The syntax of an object literal is the same as Javascript, but you need to quote a key when it contains non-alphabetical characters. You can use a spread operator.

Regular Expression

The syntax of a regular expression literal is the same as Javascript.

null and undefined

You can use null and undefined as literals.

Operators

You can use the following operators.

These operators have the same behaviors and precedences as JavaScript except for the following.

Conversion to Boolean

A value will be converted to a Boolean value following these rules when it’s used as a condition in a ternary operator or used as a Dynamic Visibility property in a field.

Function Definition

You can pass a function you defined to functions such as map and filter.

Use a syntax of an arrow function of JavaScript to define a function. For example, n => n * 2 in map([1, 2, 3], n => n * 2) is a function to double a number.

Defined Functions

You can invoke these function in an expression. To invoke a function, pass arguments separated by , and enclosed by () following the function name.

addDate

Adds a specified time to a specified date, string or a number. Specify time to add as a number as the second argument. You can optionally specify a unit of the time as the third argument. A possible units are days, hours, minutes, seconds, and milliseconds.

When you specify a date, it adds a specified time to it and returns the result date. It treats as if you specified milliseconds as a unit if you omit it.

When you specify a number, it converts the number to a date as the number of milliseconds since 1970-01-01 00:00:00 (UTC), then adds a specified time and returns a date as a number of milliseconds since 1970-01-01 00:00:00 (UTC). It treats as if you specified milliseconds as a unit if you omit it.

When you specify a string in YYYY-MM-DD format, it adds a specified time to it and returns a string in YYYY-MM-DD format. It treats as if you specified days as a unit if you omit it.

When you specify a string in HH:mm:ss format, it adds a specified time to it and returns a string in HH:mm:ss format. It treats as if you specified milliseconds as a unit if you omit it. If the result exceeds 24 hours, it wraps. For example, it returns "04:00:00" instead of "28:00:00".

Examples
addDate(parseDateTime("2021-12-08T10:34:45.000Z"), 10 * 60 * 60 * 1000)
// => Date representing 2021-12-8 20:34:45 (UTC)

addDate(parseDateTime("2021-12-08T10:34:45.000Z"), 3, "days")
// => Date representing 2021-12-11 10:34:45 (UTC)

addDate(1638959685000, 10 * 60 * 60 * 1000)
// => 1638995685000

addDate(1638959685000, 3, "days")
// => 1639218885000

addDate("2021-12-08", 3)
// => "2021-12-11"

addDate("2021-12-08", 4 * 24 * 60 * 60 * 1000, "milliseconds")
// => "2021-12-12"

addDate("10:34:45", 10 * 1000)
// => "10:34:55"

addDate("10:34:45", 15, "hours")
// => "01:34:55"

ceil

Computes a number rounded up to a specified precision.

Examples
ceil(10.5)
// => 11

ceil(10.513, 2)
// => 10.52

contains

Checks if a string, an array or object contains a specified value.

Examples
contains("abcdefg", "cde")
// => true

contains("abcdefg", "x")
// => false

contains([1, 2, 3], 3)
// => true

contains([1, 2, 3], [2, 3])
// => false

contains({ x: 1, y: 2 }, 2)
// => true

count

Computes the length of a string, or the number of elements in an array or an object.

Examples
count("abcdefg")
// => 7

count([1, 2, 3])
// => 3

count({ x: 1, y: 2 })
// => 2

encodeURIComponent

Encode a string to embed it into a URI.

Examples
encodeURIComponent("100% ABC")
// => "100%25%20ABC"

encodeURIComponent("こんにちは")
// => "%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF"

escapeHtml

Escapes a string as HTML. The following conversions will be applied.

Examples
escapeHtml("<A & B>")
// => "&lt;A &amp; B&gt;"

filter

Applies a function to each value in an array or an object, and returns an array or an object containing only values for which the function returns a truthy value.

Examples
filter([1, 2, 3], n => n % 2 == 1)
// => [1, 3]

filter({ x: 1, y: "foo", z: 300 }, v => count(string(v)) == 3)
// => { y: "foo", z: 300 }

floor

Computes a number rounded down to a specified precision.

Examples
floor(10.5)
// => 10

floor(10.513, 2)
// => 10.51

formatDateTime

Convert a date to a string. YYYY-MM-DD'T'HH:mm:ss.SSS'Z' is used when you don’t specify a format. See Format for available formats.

You can specify timezone like Asia/Tokyo with a format. The application’s timezone (when an expression is evaluated on a server) or the timezone of your device (when it is evaluated in Platio App) is used when you don’t specify a timezone.

Examples
formatDateTime(parseDateTime("2018-06-30T12:30:00.000Z"))
// => "2018-06-30T12:30:00.000Z"

formatDateTime(parseDateTime("2018-06-30T12:30:00.000Z"), "YYYY/MM/DD HH:mm:ss")
// => "2018/06/30 12:30:00"

formatDateTime(parseDateTime("2018-06-30T12:30:00.000Z"), "YYYY/MM/DD HH:mm:ss", "Asia/Tokyo")
// => "2018/06/30 21:30:00"

formatNumber

Format a number to a string.

You can specify some of these options as a second parameter.

See Intl.NumberFormat for details.

Examples
formatNumber(1234.56)
// => "1,234.56"

formatNumber(1234.56, { useGrouping: false })
// => "1234.56"

formatNumber(1234.56, { minimumIntegerDigits: 5 })
// => "01,234.56"

formatNumber(1234.56, { minimumFractionDigits: 3 })
// => "1,234.560"

formatNumber(1234.56, { maximumFractionDigits: 1 })
// => "1,234.5"

formatTime

Convert a specified time to a string using a specified format. You can specify time either by a number representing milliseconds passed since the beginning of the day, or a string in HH:mm:ss format. See Format for available formats.

Examples
formatTime((9 * 60 + 30) * 60 * 1000, "HH:mm:ss")
// => "09:30:00"

formatTime("08:34:00", "H:mm")
// => "8:34"

formatTime("13:30:00", "h:mma")
// => "1:30pm"

map

Applies a function to an array or an object and returns an array or an object containing the results.

Examples
map([1, 2, 3], n => n * 2)
// => [2, 4, 6]

map({ x: 10, y: "foo" }, v => string(v))
// => { x: "10", y: "foo" }

match

Matches a string against a regular expression. A result will be an array of strings. The first element is a string matching against the entire regular expression. The following elements will be strings captured by groups in the regular expression. However, strings matching against the regular expression are returned as an array when you specify g flag to the regular expression. This function returns null when the string doesn’t match.

Examples
match("ABC", /B/)
// => ["B"]

match("ABC", /(.)B/)
// => ["AB", "A"]

match("ABCBA", /(.)B/g)
// => ["AB", "CB"]

match("ABC", /X/g)
// => null

number

Converts a value to a number.

Examples
number("10.5")
// => 10.5

number(true)
// => 1

number(parseDateTime("2018-06-30T12:30:00.000Z"))
// => 1530361800000

number("abc")
// => NaN

parseDate

Converts a string in YYYY-MM-DD format to a date in a specified timezone. You can specify timezone like Asia/Tokyo. The application’s timezone (when an expression is evaluated on a server) or the timezone of your device (when it is evaluated in Platio App) is used when you don’t specify a timezone.

Examples
parseDate("2018-06-30")
// => Date representing 2018-6-30 00:00:00 (UTC)

parseDate("2018-06-30", "Asia/Tokyo")
// => Date representing 2018-6-29 15:00:00 (UTC)

parseDate("2018/06/30")
// => undefined

parseDateTime

Converts a string in YYYY-MM-DD'T'HH:mm:ss.SSS'Z' format to a date, or converts a number to a date as the number of milliseconds since 1970-01-01 00:00:00 (UTC).

Examples
parseDateTime("2018-06-30T12:30:00.000Z")
// => Date representing 2018-6-30 12:30:00 (UTC)

parseDateTime(1530361800000)
// => Date representing 2018-6-30 12:30:00 (UTC)

parseDateTime("2018/06/30 12:30:00")
// => undefined

parseTime

Converts a string in HH:mm:ss format to a number in milliseconds.

parseTime("09:00:00")
// => 32400000

parseTime("9:00:00")
// => undefined

quote

Quote a value with "". " and \ will be escaped by \. A value will be converted to a string if it’s not a string.

Examples
quote("abc")
// => "\"abc\""

quote("a\"b\\c")
// => "\"a\\\"b\\\\c\""

quote(10.5)
// => "10.5"

quote(true)
// => "true"

quote([1, 2, 3])
// => "1,2,3"

quote({ x: 1 })
// => "[object Object]"

reduce

Reduces an array or an object by applying a function.

Examples
reduce([1, 2, 3], (a, n) => a + n, 0)
// => 6

reduce({ x: 10, y: "foo" }, (a, v) => a + v, "")
// => "10foo"

replace

Replaces a substring matching against a regular expression with a specified string. It returns the original string when it doesn’t match.

It replaces the first occurrence without g flag for the regular expression, and replaces all the occurrences with g flag.

Examples
replace("ABC", /B/, "XYZ")
// => "AXYZC"

replace("ABC", /X/, "PQR")
// => "ABC"

replace("ABC", /^(.)/, "$1X")
// => "AXBC"

replace("A B C", / /g, "")
// => "ABC"

round

Computes a number rounded to a specified precision.

Examples
round(10.5)
// => 11

round(10.513, 2)
// => 10.51

sort

Sorts an array. It returns undefined if the first argument isn’t an array.

An array will be sorted by comparing elements as numbers when all the elements are numbers, and as strings otherwise, if you don’t pass a function to compare elements.

You need to make it return a negative number if the first argument should be placed before the second argument, and return a positive number if the first argument should be placed after the second argument, and return 0 if they should keep their relative positions, when you pass a function to compare elements.

Examples
sort([51, 9, 10, 9])
// => [9, 9, 10, 51]

sort(["51", "9", "10", "9"])
// => ["10", "51", "9", "9"]

sort(["abc", "d", "ef", "ghi"], (lhs, rhs) => count(lhs) - count(rhs))
// => ["d", "ef", "abc", "ghi"]

split

Splits a string by a specified string or a regular expression and returns an array of strings.

Examples
split("A,B", ",")
// => ["A", "B"]

split("AB", ",")
// => ["AB"]

split(",A,B,", ",")
// => ["", "A", "B", ""]

split("A1B2C3", /[A-Z]/)
// => ["", "1", "2", "3"]

split("1a2b3", /([a-z])/)
// => ["1", "a", "2", "b", "3"]

string

Converts a value to a string.

Examples
string("abc")
// => "abc"

string(10.5)
// => "10.5"

string(true)
// => "true"

string([1, 2, 3])
// => "1,2,3"

string({ x: 1 })
// => "[object Object]"

substring

Extracts a substring from a string at the specified start index and length.

You can specify a non-negative integer as a 0-based start index. It returns undefined when you specify a non-integer or a negative integer, and an empty string when you specify a number larger than length of the string.

You can specify a non-negative integer as length. It returns undefined when you specify a non-integer or a negative integer. It returns a string to the end if the specified length exceeds length of the string.

Examples
substring("abc123", 0, 2)
// => "ab"

substring("abc123", 2, 10)
// => "c123"

substring("abc123", 10, 2)
// => ""

sum

Computes the sum of the numbers in an array.

Examples
sum([1, 2, 3, 4, 5])
// => 15

toLowerCase

Convert a string to lowercase.

Examples
toLowerCase("ABCabc123")
// => "abcabc123"
toLowerCase("ABCabc123")
// => "abcabc123"

toUpperCase

Convert a string to uppercase.

Examples
toUpperCase("ABCabc123")
// => "ABCABC123"
toUpperCase("ABCabc123")
// => "ABCABC123"

Differences from JavaScript

Platio Expression looks similar to JavaScript, but some behaviors are different. Also, you cannot use all features of JavaScript. In this section, we’ll list some of these differences, but there’re still other differences.

Statements

You can only use expressions, but cannot use statements. 10 + 5; "test" is an invalid expression, for example. You cannot use control syntaxes such as for, if, while that need statements.

String Literals

A string literal needs to be quoted using double-quotes ("). You cannot use single-quotes ('). "test" is a valid expression, but 'test' is not.

Referring to Properties of an Object and an Array

You can use . syntax to access properties of an object and an array only when you’re referring to parameters. record.values.c7faa419.value is a valid expression when record is a parameter, but { key: "value" }.key is not. Specify a key in [] like { key: "value" }["key"] in this case.

Referring to Properties of undefined and null

Referring to a property of undefined or null doesn’t cause an error and becomes undefined unlike JavaScript. record.values.cb3bbfb0.value will be undefined even when no value is specified for the field whose column ID is cb3bbfb0.

Semantics of Equality Operators

== and != in Platio Expressions are strict comparisons. They’re equivalents of === and !== in JavaScript respectively.

Method Invocations

You cannot invoke a method of an object in an expression. date.getTime() is an invalid expression, for example.

Function Definitions

Functions need to defined using an arrow function syntax. map([1, 2], n => n * 2) is a valid expression, but map([1, 2], function(n) { return n * 2 }) is not.

NaN and Infinite

It’ll be converted to undefined when an expression was evaluated to either of NaN, Infinite or -Infinite.