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.
Let’s see some examples.
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.
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.
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
}
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.
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"))))
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.
c63ae565
Test Value
c00bb867
[10, 15, 20]
record
{
"values": {
"c63ae565": {
"type": "String",
"value": "Test Value"
},
"c00bb867": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 10
},
{
"type": "Number",
"value": 15
},
{
"type": "Number",
"value": 20
}
]
}
}
}
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.
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.
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
.
These types have literals.
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.
"abc"
"\""
"\n"
You can use a decimal number. Using exponential like
1e10
is not supported.
10
103.51
-435.2
The syntax of a boolean literal is the same as Javascript.
true
false
There is no literal for Date.
The syntax of an array literal is the same as Javascript. You can use a spread operator.
[1, 2, 3]
["a", "b", "c"]
[1, 2, ...[3, 4]]
["a", "b", x] // x is an array
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.
{ x: 10, y: "abc" }
{ "x.y": 20 }
{ x: 10, y: "abc", ...{ z: true } }
{ x: 10, y: "abc", ...z } // z is an object
The syntax of a regular expression literal is the same as Javascript.
/pattern/
/pattern/ig
null
and
undefined
You can use null
and undefined
as
literals.
You can use the following operators.
+
-
*
/
%
**
||
&&
!
==
!=
<
<=
>
>=
?:
(Ternary operator)These operators have the same behaviors and precedences as JavaScript except for the following.
==
and !=
perform strict comparisons like
===
and !==
in JavaScript.**
. For example, -2 ** 3
will be treated as
-(2 ** 3)
.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.
undefined
and null
are converted to
false
.true
if not empty, and
false
otherwise.true
unless it’s
0
or NaN
.true
.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.
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"
.
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.
ceil(10.5)
// => 11
ceil(10.513, 2)
// => 10.52
contains
Checks if a string, an array or object contains a specified value.
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.
count("abcdefg")
// => 7
count([1, 2, 3])
// => 3
count({ x: 1, y: 2 })
// => 2
encodeURIComponent
Encode a string to embed it into a URI.
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.
<
-> <
>
-> >
&
-> &
"
-> "
escapeHtml("<A & B>")
// => "<A & B>"
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.
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.
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.
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.
useGrouping
Whether to use grouping separators. It’ll use grouping separators if not specified.
minimumIntegerDigits
The minimum number of integer digits to use. It’ll be 1
if not specified.
minimumFractionDigits
The minimum number of fraction digits to use. It’ll be 0
if not specified.
maximumFractionDigits
The maximum number of fraction digits to use. It’ll be the larger of
minimumFractionDigits
and 3
if not
specified.
See Intl.NumberFormat for details.
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.
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.
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.
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.
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.
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).
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.
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.
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.
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.
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.
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.
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.
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.
substring("abc123", 0, 2)
// => "ab"
substring("abc123", 2, 10)
// => "c123"
substring("abc123", 10, 2)
// => ""
sum
Computes the sum of the numbers in an array.
sum([1, 2, 3, 4, 5])
// => 15
toLowerCase
Convert a string to lowercase.
toLowerCase("ABCabc123")
// => "abcabc123"
toLowerCase("ABCabc123")
// => "abcabc123"
toUpperCase
Convert a string to uppercase.
toUpperCase("ABCabc123")
// => "ABCABC123"
toUpperCase("ABCabc123")
// => "ABCABC123"
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.
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.
A string literal needs to be quoted using double-quotes
("
). You cannot use single-quotes ('
).
"test"
is a valid expression, but 'test'
is
not.
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.
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
.
==
and !=
in Platio Expressions are strict
comparisons. They’re equivalents of ===
and
!==
in JavaScript respectively.
You cannot invoke a method of an object in an expression.
date.getTime()
is an invalid expression, for example.
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
.