Data-binding Syntax (APL for Audio)

You use data-binding syntax to write expressions that Alexa evaluates when rendering your document. You use data-binding expressions to bind component properties to your data source, and to write conditional logic to include and exclude components depending on criteria.

About data binding expressions

You use data binding expressions inside JSON strings. A data binding expression has the form "${expression}".

You can use any number of expressions inside a string, for example: "${2}+${2} = ${2+2}".

Alexa evaluates expressions within the current data-binding context. The data-binding context is a global dictionary that supports booleans, numbers, strings, arrays, objects, and null.

Supported value types

Identifier

An identifier is a name used to identify a data-binding variable. Identifiers must follow the C identifier naming convention: [a-zA-Z_][a-zA-Z0-9_]*. That is, the identifier must start with an upper or lower-case ASCII letter or underscore and can be followed by zero or more ASCII letters, numbers, or the underscore:

${data}
${_myWord23}
${__AnUgly26_letter__examplE}

String literals

Define strings with either single or double quotes. The starting and ending quote must match. Quotes, carriage returns, and line-feeds can be escaped:

${"Double-quoted string"}
${'Single-quoted string'}
${"Inner quote: \" or '"}

Expressions can be nested inside of a string:

${"Two plus two is ${2+2}"}

Numbers

Positive, negative, and floating-point numbers are supported. Scientific notation is not supported. All numbers are doubles.

Booleans

Boolean values of true and false are supported:

${true}
${false}

Time

Time data types are supported, with a default unit of milliseconds. The only supported units are milliseconds and seconds. Use a suffix of "s" to indicate a unit of "seconds":

${1000}
${1.7s}

null

The null constant is supported:

${null}

Truthy and coercion

Data-binding expressions use different types. These types can be converted into other types. The following table summarizes these type conversions:

Object Type Example As Boolean As Number As String
Null null false 0 ""
Boolean true true 1 "true"
  false false 0 "false"
Number 23 true 23 "23"
  0 false 0 "0"
String "My dog" true 0 "My dog"
  "" false 0 ""
  "-2.3" true -2.3 "-2.3"
  "red" true 0 "red"
  "50vw" true 50 "50vw"
Array [] true 0 ""
Map {} true 0 ""
  0vh false 0 "0ch"
  23% true 0.23 "23%"
  0% false 0 "0%"
  auto true 0 "auto"
Anything else true 0 ""

Boolean coercion

A truthy value is a value that is considered true when evaluated in a boolean context. All values are truthy except for false, 0, "", and null.

Number coercion

The boolean "true" value converts to the number 1. Everything else converts to 0.

String coercion

Internal types convert to strings according to the rules in the following table:

Object Example Result Description
Null null '' The null value is not rendered.
Boolean true false 'true' 'false' Boolean true & false are rendered as strings.
Number -23 '-23' Integers have no decimal places.
  1/3 '0.333333' Non-integers have decimal places.
String "My "dog" " 'My "dog" ' String values
Array […] '' Arrays are not rendered
Map {…} '' Maps are not rendered
Anything else ${Math.min} '' Math functions are not rendered.

The specific format of non-integer numbers is not defined, but should follow the C++ standard for sprintf(buf, "%f", value). This format might change based on the locale.

Operators

Arithmetic operators

The standard arithmetic operations for addition, subtraction, multiplication, division, and remainder are supported:

${1+2} // 3
${1-2} // -1
${1*2} // 2
${1/2} // 0.5
${1%2} // 1.

Addition and subtraction work for pairs of numbers.

The addition operator also acts as a string-concatenation operator if either the left or right operand is a string:

${27+""}     // '27'
${1+" dog"}  // '1 dog'
${"have "+3} // 'have 3'

Multiplication, division, and the remainder operator work for pairs of numbers.

The remainder operator behaves as in JavaScript:

${10 % 3}  // 1
${-1 % 2}  // -1
${3 % -6}  // 3
${6.5 % 2} // 0.5

Logical operators

The standard logical and/or/not operators are supported:

${true || false} // true
${true && false} // false
${!true}         // false
The && returns the first operand when the operand is not truthy and the second otherwise. The   operator returns the first operand if it is truthy and the second otherwise:
${7 && 2}    // 2
${null && 3} // null
${7 || 2}    // 7
${0 || -16}  // -16

Comparison operators

Comparison operators return boolean values:

${1 < 2}
${75 <= 100}
${3 > -1}
${4 >= 4}
${myNullValue == null}
${(2>1) == true}
${1 != 2}

The comparison operators don't apply to arrays and objects.

Null coalescing operator

The ?? operator is the null-coalescing operator. It returns the left-hand operand if the operand is not null; otherwise it returns the right-hand operand. You can chain the null-coalescing operator:

${person.name ?? person.surname ?? 'Hey, you!'}

The null-coalescing operator returns the left-hand operand when it is anything but null:

${1==2 ?? 'Dog'}   // returns false
${1==2 || 'Dog'}   // returns 'Dog'

Ternary operator

The ternary conditional operator (${a ? b : c}) evaluates the left-hand operand. If it evaluates to true or a truthy value, the middle operand is returned. Otherwise the right-hand operand is returned:

${person.rank > 8 ? 'General' : 'Private'}

Array and object access

Array

Array access uses the [] operator, where the operand should be an integer. Arrays also support the .length operator to return the length of the array. Accessing an element outside of the array bounds returns null:

${myArray[4]}     // 5th element in the array (0-indexed)
${myArray.length} // Length of the array
${myArray[-1])}   // Last element in the array
${myArray[myArray.length]}  // Returns null (out of bounds)

Passing a negative index counts backwards through the array:

${a[-1] == a[a.length - 1]} // True

Object

Objects support the . operator and the [] array access operator with string values:

${myObject.name}    // The 'name' property of myObject
${myObject['name']} // The 'name' property of myObject

An undefined property returns null. Calling the . or [] operator on null returns null:

${myNullObject.address.zipcode} // Returns null

The right-side operand of the dot operator must be a valid identifier.

Function calls

Functions

Data-binding supports a limited number of built-in functions. Functions use the form:

functionName( arg1, arg2, … )

Functions don't require arguments. A function returns a single value.

Built-in functions

Property Description Example
Math.abs(x) Return the absolute value of x ${Math.abs(-2.3)} == 2.3
Math.acos(x) The arccosine of x ${Math.acos(1)} == 0
Math.asin(x) The arcsine of x ${Math.asin(0)} == 0
Math.atan(x) The arctangent of x ${Math.atan(1)} == 0.7853981633974483
Math.ceil(x) Return the smallest integer greater than or equal to x. ${Math.ceil(2.3)} == 3
Math.clamp(x,y,z) Return x if y<x, z if y>z and otherwise y. ${Math.clamp(1, 22.3,10)} == 10
Math.cos(x) The cosine of x ${Math.cos(0)} == 1
Math.floor(x) Return the largest integer less than or equal to x. ${Math.floor(2.3)} = 2
Math.max(x1,x2,…) Return the largest argument ${Math.max(2,3)} == 3
Math.min(x1,x2,…) Return the smallest argument ${Math.min(2,3)} == 2
Math.PI The value of π 3.141592653589793
Math.random() A random number between 0 and 1 ${Math.random()} == 0.7113654073137101 (but not every time!)
Math.round(x) Return the nearest integer to x ${Math.round(2.3)} == 2
Math.sign(x) The sign of x: -1, 0, or +1 ${Math.sign(-43.1) == -1
Math.sin(x) The sine of x ${Math.sin(Math.PI/6)} == 0.5
Math.sqrt(x) The square root of x ${Math.sqrt(9)} == 3
Math.tan(x) The tangent of x ${Math.tan(Math.PI/4)} == 0.5
String.slice(x,y[,z]) Return the subset of x starting at index y and extending to but not including index z. If z is omitted, the remainder of the string is returned. If y is a negative number, select from the end of the string. ${String.slice("berry", 2, 4)} == "rr" ${String.slice("berry", -2)} == "ry"
String.toLowerCase(x) Return a lower-case version of x ${String.toLowerCase("bEn")} == "ben"
String.toUpperCase(x) Return an upper-case version of x ${String.toUpperCase("bEn")} == "BEN"

Data-binding string conversion

Because APL is serialized in JSON, all data-bound expressions are defined inside of a JSON string:

{
  "MY_EXPRESSION": "${....}"
}

If there are no spaces between the quotation marks and the data-binding expression, the result of the expression is the result of the data-binding evaluation. For example:

"${true}"               -> Boolean true
"${2+4}"                -> Number 6
"${0 <= 1 && 'three'}"  -> String 'three'

When extra spaces are in the string outside of the data-binding expression or when two data-binding expressions are juxtaposed, the result is a string concatenation:

" ${true}"     -> String ' true'
"${2+4} "      -> String '6 '
"${2+1}${1+2}" -> String '33'