APL Data-Binding Evaluation (APL 1.8)
(This is not the most recent version of APL. Use the Other Versions option to see the documentation for the most recent version of APL)
Alexa Presentation Language (APL) documents rely on data-binding to incorporate user-provided data, include styles and other visual resources, pass parameters into layouts, and conditionally inflate layouts based on data. To use data-binding in your document, you write data-binding expressions, which are JSON strings with an embedded ${...}
substring. This document describes how Alexa evaluates these expressions in the latest version of APL.
Data-binding syntax is covered separately.
Data-binding algorithm
Consider the definition of a Text component in a sample APL document.
{
"type": "Text",
"text": "There are ${data.value} peas in the pod",
"color": "@myBlue",
"fontSize": "${@textSizePrimary * 1.2}"
}
This definition includes three expressions to evaluate. First, the text
has the data.value
number inserted into a longer expression. Second, the color
is set to "myBlue", which in this case refers to a user-defined resource. Finally, the fontSize
is set to 1.2 times larger than the standard primary text size of the document.
All of these expressions are evaluated using the following three-step algorithm: Expression evaluation, Resource lookup, and type coercion.
Step 1: Expression evaluation
If the right-hand side (RHS) is a string, the algorithm scans the string for data-binding expressions (embedded '${}'
). If it finds one or more embedded expressions, the entire string is converted to an abstract syntax tree (AST). For example, the text
example above is converted to this tree:
Concatenate
String("There are ")
AttributeLookup
Symbol("data")
String("value")
String(" peas in the pod")
The AST is now evaluated using the current data-binding context. The data-binding context is a JSON dictionary of key-value pairs, where each value can be a number, boolean, object, array, or string. Operators such as "+" do implicit type conversion as necessary. For example, if the data-binding context is as shown here, then the "data" symbol will return the object "{ value: 5}" and the attribute accessor of "value" will return the number 5. The Ternary concatenation operator has two strings and a number, and thus will cast the number as a string and return "There are 5 peas in the pod" as a string value.
{
"data": {
"value": 5
}
}
Step 2: Resource lookup
After data-binding, string values may be a reference to a system-defined resource. Resources references start with "@" and consist of a single, unhyphenated word. Resources are typed. If you refer back to the original example, the color of the Text is set to @myBlue
. The evaluator looks for a resource with the name @myBlue
in the colors resources. Assume that the user has provided a resources block of the form:
{
"resources": [
{
"colors": {
"myBlue": "#0033ff"
}
}
]
}
Then the resource lookup stage will translate "@myBlue" into "#0033ff".
Step 3: Type coercion
The final step is to ensure that the set value is of the correct type. In the color
example, a string value of "#0033ff" has been returned. Since the target value is known to be a color, this string value must be converted into the correct internal type for a color.
Initial data-binding context
The data-binding context is cleared when a new APL document is inflated. The cleared data-binding context has the following pre-defined objects:
Property | Description | Dynamic |
---|---|---|
|
Display state of the document on the screen |
Yes |
|
Run time in milliseconds of this document |
Yes |
|
Information about the current runtime environment |
No |
|
Local time in milliseconds |
Yes |
|
Built-in mathematical functions. See Function calls. |
No |
|
Built-in string functions. See Function calls. |
No |
|
Built-in time functions (see Time functions) |
No |
|
UTC time in milliseconds |
Yes |
|
Configuration information about the current device. See Viewport Object in the Data-binding Context |
No |
displayState
Returns a value indicating the current state of the document on the screen. The displayState
can be one of the values shown in the following table.
Name | Description |
---|---|
|
The document isn't visible on the screen. The document doesn't generate tick events or generates the events at irregular intervals. A well-behaved document stops all animations when the document is in this state. |
|
The document might be visible on the screen or it might be mostly obscured by other content on the screen. The document isn't the primary focus of the system. The document does generate tick events, but document animations should be restricted to the minimum. |
|
The document is visible on the screen and at the front. |
The displayState
property is read-only.
elapsedTime
The elapsedTime
property is a monotonically increasing time in milliseconds since this document was created. It starts at zero when the document is rendered and counts upwards while the document is visible on the screen. The elapsedTime
property does not advance when the document is "frozen" or hidden from the user's view.
environment
The environment
object contains runtime information about the operating APL environment. The environment
values don't change during the lifetime of the APL document.
The following table shows the properties in the environment
object. The Can set column indicates environment properties that you can set in the APL document by using the APL document environment
property.
Property | Type | Can set? | Description |
---|---|---|---|
|
String |
No |
Name of the runtime environment |
|
String |
No |
Version of the runtime environment |
|
Boolean |
No |
True if the |
|
One of: |
No |
Animation characteristics of the runtime |
|
String |
No |
Supported version of APL. The current version of APL is 2024.3 |
|
Boolean |
No |
True if the |
|
Map |
No |
Requested and supported extensions |
|
Number |
No |
Percentage of the normal font size requested by the operating system |
|
|
Yes |
The default language (BCP-47 format) used for text display |
|
One of: |
Yes |
The default component and text layout direction for the document |
|
One of: |
No |
Indicates whether this inflation of the document is the initial inflation, or a later reinflation |
|
One of: |
No |
Screen mode setting |
|
Boolean |
No |
True if a screen reader is enabled |
|
Object |
No |
Configuration information about standard system timing |
agentName
The name of the runtime environment. This is a string assigned by the runtime and is meant to assist with debugging. If available, please include this information if you report APL bugs or issues. It is not guaranteed to have any particular form or structure.
Don't use this value to provide conditional responses based on these values. These values could change if an agent is updated.
agentVersion
The version of the runtime environment. This is a string assigned by the runtime and is meant to assist with debugging. If available, please include this information if you report APL bugs or issues. It is not guaranteed to have any particular form or structure.
Don't use this value to provide conditional responses based on these values. These values could change if an agent is updated.
allowOpenURL
A boolean value. True if the OpenURL
command is enabled, false
otherwise.
animation
Indicates the level of animation support on the device. The valid values for animation
are:
Name | Description |
---|---|
none |
Animation is not supported on this device. All animation commands run in fast mode. |
slow |
Animation is supported on this device, but has visible performance limitations. |
normal |
Standard animations run at acceptable speeds on this device. |
Always check this value and either simplify or drop animations if it is set to slow
.
aplVersion
The version of APL supported by this device. This feature was added in APL version 1.1. For APL version 2024.3, this returns "2024.3".
This property does not exist in APL 1.0, so it returns null
.
For example, to create an attribution string based on the current version of APL, you could write:
{
"resources": [
{
"strings": {
"versionString": "This is APL version 1.0 or earlier"
},
"colors": {
"versionColor": "red"
}
},
{
"when": "${environment.aplVersion}",
"strings": {
"versionString": "This is an unexpected APL version: ${environment.aplVersion}"
},
"colors": {
"versionColor": "yellow"
}
},
{
"when": "${environment.aplVersion == '2024.3'}",
"strings": {
"versionString": "This is the expected APL version 2024.3"
},
"colors": {
"versionColor": "green"
}
}
]
}
When you use any features introduced in 1.1 or later, be sure to wrap that section of the document in a when
clause that checks the aplVersion
.
disallowVideo
True if the Video
component is disabled in this runtime. A Video
component still takes space on the screen, but videos are not be played and the component does not respond to commands.
extension
The extension
property reports the state of requested and loaded extensions. It contains a map of string names to extension-defined values. The string names are the name values of extensions requested by the APL document (see extensions
). For example, if the document requested the extension "aplext:remotebutton:v13" with the name of "Button", then the data-binding expressions could be used to check for the presence of that extension:
"when": "${environment.extension.Button}"
Note that maps are truthy. For example, an extension might provide a map of information in the environment for the "Button" extension:
{
"author": "Fred Flintstone",
"version": "1.3"
}
Then in your document, you could write:
{
"type": "Text",
"when": "${environment.extension.Button}",
"text": "Loaded version ${environment.extension.Button.version} of the extension"
}
This Text component will only appear when the "Button" extension is present and will display the version of the loaded extension.
fontScale
Returns the relative size of fonts to display as specified by the operating system accessibility settings. Most operating systems have a user-controlled accessibility setting to specify that fonts should be made larger than normal to help vision-impaired users. This numeric value is the user-requested scaling factor for font size. The default setting is 1.0; many operating systems support accessibility scaling of 1.5 and 2.0 as well.
lang
The lang
environment property reports the default runtime language. It contains a BCP-47 string (such as "en-US" or "ja-JP").
You can use the lang
property to select language-appropriate resources.
The following example shows how to create an attribution string resource that changes depending on the specified language.
Resource definition
{
"resources": [
{
"strings": {
"helloText": "Hello"
}
},
{
"when": "${environment.lang == 'ja-JP'}",
"strings": {
"helloText": "こんにちは"
}
}
]
}
Resource use
{
"type": "Text",
"text": "@helloText"
}
The runtime software specifies the default lang
value. This value might be an empty string and therefore not match any specific language settings. You can override the default lang
value by using the APL document environment
property.
The best practice for setting the document-level lang
property is to use the document environment
property to bind lang
to a value your data source. In your skill code, set the lang
value in your data source based on the locale of the skill request.
layoutDirection
The layoutDirection
environment property reports the default text and component layout direction. The valid values for layoutDirection
are:
Name | Description |
---|---|
|
Left-to-right |
|
Right-to-left |
For details about how layoutDirection
affects components, see layoutDirection
.
You can use The layoutDirection
property to create direction-appropriate resources.
The following example shows how to create a resource that displays a forward arrow. For a left-to-right document, the resource displays the unicode character for an arrow that points to the right. For a right-to-left document, the resource displays the unicode character for an arrow pointing to the left.
Resource definition
{
"resources": [
{
"strings": {
"forwardArrow": "→"
}
},
{
"when": "${environment.layoutDirection == 'RTL'}",
"strings": {
"forwardArrow": "←"
}
}
]
}
Resource use
{
"type": "Text",
"text": "@forwardArrow"
}
The runtime software specifies the default layoutDirection
value. You can override the default lang
value by using the APL document environment
property.
The best practice for setting the document-level layoutDirection
property is to use the document environment
property to bind layoutDirection
to a value your data source. In your skill logic, set the layoutDirection
value in your data source based on the locale of the skill request.
reason
The reason
environment property returns initial
the first time a document inflates and reinflation
if the document reinflates with the Reinflate
. For details about resizing and reinflating documents, see Support Tablets and Other Devices that Can Change Size.
screenMode
Returns the accessibility settings for how colors should be displayed. There are two possible values: normal
and high-contrast
. When high-contrast
is requested, the colors used to display text and images should be selected to ensure vision-impaired users can distinguish between different elements.
screenReader
When true
, indicates that the user has enabled a screen reader for the device.
timing
Returns standard system timing information. These values change based on device characteristics and accessibility settings. Use these values if you set timing values in your document instead of using absolute numbers.
All timing values are in milliseconds; all velocity values are in dp per second. The example values shown here are for reference only and might be different at run time.
Name | Example | Description |
---|---|---|
doublePressTimeout |
300 | Maximum time between releasing the first tap and starting the second tap to consider this a double-press event. |
longPressTimeout |
500 | Minimum time to hold a press event before turning into a long press event. |
minimumFlingVelocity |
50 | Minimum velocity needed to initiate a fling (dp/second) |
pressedDuration |
64 | Duration to show the "pressed" state of a component when programmatically invoked. |
tapOrScrollTimeout |
100 | When deciding if the user was tapping a component or scrolling/swiping a region, this is the time to wait to see if the user moves the touch point. |
localTime
The localTime
property is the number of milliseconds that has passed since the Unix epoch (Jan 1, 1970, 00:00:00 UTC), adjusted by the local timezone offset from UTC and by daylight saving time. The localTime
property is derived from the utcTime
property. Please note that the localTime
property might "jump" forward or backwards with any change in system time such as daylight saving or a timezone change. Do not use localTime
to measure event durations.
utcTime
The utcTime
property is the number of milliseconds that have passed since the Unix epoch (Jan 1, 1970, 00:00:00 UTC). The utcTime
property normally increases monotonically, but might shift around slightly for devices using NTP to periodically synchronize with a time server. The utcTime
property is suitable for measuring true elapsed time.
Extending the data-binding context
APL layouts have parameters. Inflating a layout adds the named parameters to the data-binding context, as shown in this example.
"myQuoteLayout": {
"parameters": [ "quotes" ],
"item": {
"type": "Text",
"text": "${quotes.shakespeareQuotes[0]}"
}
}
// Inflation
{
"type": "myQuoteLayout",
"quotes": {
"shakespeareQuotes": [
"This above all: to thine own self be true...",
"The lady doth protest too much, methinks.",
"Love all, trust a few, do wrong to none."
],
"shakespeareSonnets": [
"Weary with toil, I haste me to my bed, The dear repose for limbs..."
]
}
In this example, quotes
is a parameter for the custom myQuoteLayout
. When myQuoteLayout
is used, the data-binding context is extended by adding a new quotes
property with a matching value. If quotes
has not been specified, the default value for quotes
(usually null) will be added to the data-binding context. This augmented data-binding context is valid only for the inflation of the custom layout and its children.
Extensions to the data-binding context
As components are inflated, the data-binding context is extended to pass additional information to the inflated component.
Component bind extension
Each component has an optional bind property that extends the current data-binding context. The bind property is an ordered array of (name, value, type) tuples. Each value is evaluated in the current data-binding context and then added to the context.
Component child extension
Components that can contain multiple child components add the following global names to the data-binding context.
Name | Description |
---|---|
data | New data assigned from a user-specified data array during component inflation. |
index | The 0-based index of the current child. |
ordinal | The 1-based ordinal of the current child. See numbering under Sequence and Container components to see how ordinals work. |
length | The total number of children in the current component. |
Note that data
and ordinal
are only set if the appropriate property has been set in the component.
For the list of multi-child components, see Multi-child Component Properties.
Explicitly Propagating Data Binding Context
In some cases, the index
, ordinal
, or length
property of a child must be propagated down. For example, if a Sequence's child is itself a Container, then the index
property for the children of the Container will be based on the child Container rather than the Sequence. In a situation like this, to propagate the Container's index
to its children, you can use the "bind" property as follows:
{
"type": "Sequence",
"width": "100%",
"height": "100%",
"numbered": true,
"data": "${payload.templateData.properties.rows}",
"item": {
"type": "Container",
"bind": [
{
"name": "parentIndex",
"value": "${index}"
}
],
"items": [
{
"type": "Text",
"text": "Index ${parentIndex}"
}
]
}
}
Resource definitions
New resources defined in a package are added to the current data-binding context following the pattern
@
Data-binding with arrays
Many APL expressions involve evaluating an array. APL supports type coercion of arrays, implicit array-ification, and interpolation of data-bound expressions into arrays.
Array type coercion
If a property is defined as holding an array of a known type, then during property assignment each element in the array will be coerced to that type. For example, a layout expecting an array of numbers would coerce each element of that array into a number during assignment.
Implicit array-ification
For convenience, all APL properties that take an array of values will also accept a single property without the array brackets. For example, the items
property of a container is defined as an array of component. If only a single item is passed, these approaches are equivalent:
"item": {<<ITEM>>}
"item": [ {<<ITEM>>} ]
The APL runtime expands both of these into an array of length 1.
Many of the properties that expect an array have a plural alias. Thus, item
and items
are
the same property.
Interpolation of data-bound expressions into arrays
Array expansion supports the interpolation of arrays into arrays. For example:
// Context
{
"a": "value",
"b": [ "alpha", "bravo" ]
}
"values": "${a}" -> values = [ "value" ] // Implicit array-ification
"values": [ "${a}" ] -> values = [ "value" ]
"values": "${b}" -> values = [ "alpha", "bravo" ]
"values": [ "x", "${b}", "${a}" ] -> values = [ "x", "alpha", "bravo", "value" ]
The rules of array-ification are:
-
If the value is a string, evaluate it using data-binding and coerce it to the correct type (and apply array-ification).
-
If the value is an array, for each element of the array that is a string, evaluate it using data binding. If the result is a single item, insert it in the array. If it is an array of items, insert all of them into the array.
Last updated: Nov 28, 2023