APL Data-Binding Evaluation


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 ${...} sub-string. This document describes how Alexa evaluates these expressions in the latest version of APL.

For details about data-binding syntax, see Data-binding syntax.

For details about the #{...} syntax for deferred data-binding evaluation, see Deferred evaluation

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 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.

Alexa evaluates these expressions by using the following three-step algorithm: expression evaluation, resource lookup, and type coercion.

Step 1: Expression evaluation

If the right-hand side of the expression 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 in the earlier example is converted to the following 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 in the following example, the data symbol returns the object {value: 5} and the attribute accessor of "value" returns the number 5. The ternary concatenation operator has two strings and a number, and therefore casts the number as a string and returns "There are 5 peas in the pod" as a string value.

{
  "data": {
    "value": 5
  }
}

Step 2: Resource lookup

After data-binding, string values might refer to a system-defined resource. Resources references start with "@" and consist of a single, unhyphenated word. Resources are typed. If you refer 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 translates "@myBlue" into #0033ff.

Step 3: Type coercion

The final step verifies that the set value is of the correct type. In the color example, a string value of "#0033ff" has been returned. Because 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

displayState

Display state of the document on the screen

Yes

elapsedTime

Run time in milliseconds of this document

Yes

environment

Information about the current runtime environment

No

localTime

Local time in milliseconds

Yes

Array

Built-in array functions. Function calls.

No

Log

Built-in logging functions. Function calls.

No

Map

Built-in map functions. See Function calls.

No

Math

Built-in mathematical functions. See Function calls.

No

String

Built-in string functions. See Function calls.

No

Time

Built-in time functions (see Time functions)

No

utcTime

UTC time in milliseconds

Yes

viewport

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

hidden

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.

background

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.

foreground

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 after 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 doesn't 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

agentName

String

No

Name of the runtime environment

agentVersion

String

No

Version of the runtime environment

allowOpenURL

Boolean

No

True if the OpenURL command is enabled

animation

One of: none, slow, normal

No

Animation characteristics of the runtime

aplVersion

String

No

Supported version of APL. The current version of APL is 2024.3

disallowEditText

Boolean

No

True when the EditText component is disabled.

disallowDialog

Boolean

No

True when the SpeakItem and SpeakList commands are disabled

disallowVideo

Boolean

No

True if the Video component is disabled

extension

Map

No

Requested and supported extensions

fontScale

Number

No

Percentage of the normal font size requested by the operating system

lang

String

Yes

The default language (BCP-47 format) used for text display

layoutDirection

One of: LTR, RTL

Yes

The default component and text layout direction for the document

packages

Array

No

An array of the packages loaded by this document

reason

One of: initial, reinflation

No

Indicates whether this inflation of the document is the initial inflation, or a later reinflation

screenMode

One of: normal, high-contrast

No

Screen mode setting

screenReader

Boolean

No

True if a screen reader is enabled

timing

Object

No

Configuration information about standard system timing

agentName

The name of the runtime environment. This name is a string assigned by the runtime and is meant to assist with debugging. If available, include this information if you report APL bugs or issues. The agentName isn't 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, include this information if you report APL bugs or issues. The agentVersion isn't 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 This device doesn't support animation. All animation commands run in fast mode.
slow This device supports animation, but has visible performance limitations.
normal Standard animations run at acceptable speeds on this device.

Always verify this value and either simplify or drop animations when environment.animation is slow.

aplVersion

The version of APL supported by this device. This feature was added in APL version 1.1. For the current version of APL, the aplVersion property returns 2024.3.

This property doesn't exist in APL 1.0 and therefore 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.

disallowEditText

True when the EditText component is disabled in this runtime. An EditText component takes space on the screen, but component contents aren't shown. The component doesn't respond user interaction.

disallowDialog

True when the SpeakItem and SpeakList commands are disabled in this runtime. Disabled commands are ignored.

disallowVideo

True if the Video component is disabled in this runtime. A Video component still takes space on the screen, but videos don't play and the component doesn't 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 inflates when the "Button" extension is present and displays 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

LTR

Left-to-right

RTL

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.

packages

An array of the packages loaded by this document from the import property. Each entry in the array is an object with the properties shown in the following table.

Property Type Description

name

String

The package name

source

String

The package source (the empty string if undefined).

version

String

The package version

The order of the packages in the array is undefined.

Packages loaded by the ImportPackage aren't included in this array because they load after the document has been inflated.

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.

maximumTapVelocity

500

Maximum velocity to be considered a tap gesture (dp/second)

localTime

The localTime property is the number of milliseconds that has passed after 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. The localTime property might "jump" forward or backwards with any change in system time, such as daylight saving or a timezone change. Don't use localTime to measure event durations.

utcTime

The utcTime property is the number of milliseconds that have passed after 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 the following 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 isn't specified, the default value for quotes (usually null) is 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 set when 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

You might want to make the index, ordinal, or length property of a parent component available to a child component. For example, assume a Sequence component has a Container as its child component. The Container then has its own child components. The index property for the children of the Container is based on the Container rather than the Sequence. To access the index of the Sequence from within the Container, use the bind property to explicitly propagate the index down.

The following examples show a Sequence in which each child component is a Container that displays a Frame and a Text component. The Text component in each row is intended to display the index of the item relative to the Sequence.

The first example shows the problem. The expression ${index} in the Text component displays 1 for each item in the list. This problem occurs because the Container is a multi-child component with its own index property for each of its child components. Therefore, the index of the Text component within the Container refers to the index within the Container (1), not the overall list item in the Sequence.


The following example shows how to solve this problem. In this example, the Container uses bind to set a variable called parentIndex to the index property. Then, the child components of the Container use this variable instead of the index property. Each item in the Sequence now displays the index relative to the Sequence.


Resource definitions

Resources defined in a package are added to the current data-binding context following the pattern @. For example, the `myBlue` color shown in an earlier example can be explicitly referenced as `${@myBlue}` as well as implicitly by `@myBlue`.

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 is coerced to that type. For example, a layout expecting an array of numbers coerces each element of that array into a number during assignment.

Implicit array-ification

For convenience, all APL properties that take an array of values also accept a single property without the array brackets. For example, the items property of a Container accepts an array of components. Both of the following approaches are equivalent:

"item": {<<ITEM>>}
"item": [ {<<ITEM>>} ]

The APL runtime expands both of these into an array of length 1.

The properties that expect an array have a plural alias. Therefore, 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 array-ification uses the following rules:

  • If the value is a string, evaluate it using data binding, coerce it to the correct type, and apply array-ification.
  • If the value is an array, for each string element of the array, evaluate it using data binding. If the result is a single item, insert it in the array. If the value is an array of items, insert all the items into the array.

Was this page helpful?

Last updated: Dec 18, 2024