APL Standard Commands (APL 1.9 to 2022.1)
(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)
Common Properties
A single command is encoded as a JSON object. All commands contain the following properties.
Property | Type | Default | Description |
---|---|---|---|
|
String |
REQUIRED |
Type of the command |
|
String |
"" |
Optional documentation for this command |
|
Integer |
0 |
Delay time in milliseconds before this command runs. Must be non-negative. Defaults to 0. |
|
Boolean |
|
If true, disable the interaction timer. |
|
String |
"" |
Specify the sequencer that should run this command. |
|
Boolean |
|
Conditional expression. If this evaluates to |
type
Specifies the particular command to run. This may be a pre-defined primitive command types or a user-defined command.
delay
The delay
value is the amount of time in milliseconds inserted before running this command. The delay
value must be a non-negative integer, which if not specified, defaults to 0. The delay
value is ignored if the when
property resolves to false
, or if the command runs from within an event handler.
screenLock
If true, the interaction timer is disabled while this command runs. When a command with screenLock=true
finishes running, the interaction timer is reset to 0.
The screenLock
applies to the entire extent of the command including
any defined delay
. For
example, the following command holds the screen lock for 30 seconds:
{
"type": "Idle",
"delay": 30000,
"screenLock": true,
}
sequencer
If specified, the sequencer
property names the sequencer that this command should run on. The sequencer selection rules are (in order):
- If the sequencer is specified, the command runs in normal mode on that sequencer.
- Else, if the command is running in fast mode, run normally in fast mode
- Else, if the command is a subcommand of a
Sequential
orParallel
command, run in normal mode on the sequencer of theSequential
orParallel
command. - Else, run the command in normal mode on the "MAIN" sequencer.
For details about the command sequencer, see Command sequencing
when
If when
is set to true
, run the command. If false
, ignore the command. Commands
that are ignored also ignore the screenLock
property.
AnimateItem
AnimateItem
requires APL 1.1 or later. Provide an alternate experience for devices running older versions of APL.
Runs a fixed-duration animation sequence on one or more properties or bound values of a single component. For example:
{
"type": "AnimateItem",
"easing": "ease-in-out",
"duration": 600,
"componentId": "myFlyingComponent",
"value": [
{
"property": "opacity",
"to": 1
},
{
"property": "transform",
"from": [
{
"translateX": 200
},
{
"rotate": 90
}
],
"to": [
{
"translateX": 0
},
{
"rotate": 0
}
]
}
]
}
Components support animating opacity
and transform
properties. The from
value isn't required for opacity, but you must provide it for transforms.
To define a custom easing curve, you can write:
{
"type": "AnimateItem",
"easing": "path(0.25, 0.6, 0.5, 0.8, 0.75, 0.9)",
"duration": 1000,
"value": {
"property": "opacity",
"to": 1
}
}
You can animate bound properties. The following example displays a Frame
as a green box in the center of the viewport. The Frame
defines an animation in which tapping the component animates the SIDE
bound value. The animation changes the size and color of the Frame
smoothly over one second.
Click the green box in the simulator pane to see the animation. Click a second time to see the same animation in reverse.
You can also animate parameters passed to a vector graphic.
The following example defines a box with a thin stroke value as a vector graphic. Tapping the vector graphic starts an animation in which the line thickness of the box expands until the box is solid. Then the animation reverses to return to the original shape.
Click the blue box in the simulator pane to see the animation.
AnimateItem
defines the following properties in addition to normal command properties:
Property | Type | Default | Description |
---|---|---|---|
componentId |
String | SELF | The id of the component. |
duration |
Integer | REQUIRED | The duration of the animation (in milliseconds) |
easing |
linear, ease-in, … | linear | Specify an easing curve. |
repeatCount |
Integer | 0 | Number of times to repeat. |
repeatMode |
restart, reverse | restart | How repeated animations will play. |
value |
Array of animated properties | REQUIRED | An array of animated component properties. |
In fast mode, the AnimateItem
command jumps ahead to the end state of
the animation. When an AnimateItem
command stops, the animation jumps ahead to the
end state; refer to repeatMode for a discussion of how to calculate the end state.
componentId
The ID of the component. If omitted, the component issuing the
AnimateItem
command is used.
duration
The duration in milliseconds of a single pass of the animation. If the
repeatCount
property is set to greater than 0, the total duration of the
animation will be the product of the duration and one more than the
repeat count. For example, the following animation will have a total
duration of 10 seconds:
{
"type": "AnimateItem",
"duration": 1000,
"repeatCount": 9,
"repeatMode": "reverse",
"value": {
"property": "opacity",
"from": 0,
"to": 1
}
}
easing
An easing curve specifies how the value of the parameter changes over time. The curve must be a function starting at (0,0) and ending at (1,1). Two standard general ways of writing an easing curve are defined:
cubic-bezier(x1,y1,x2,y2)
: Following the CSS standard, this defines a cubic Bézier curve with starting point (0,0) and ending point (1,0). The parameterized values (x1, y1) and (x2, y2) defined the interior control points of the curve and are normally between 0 and 1.path(x1,y1,...,xN,yN)
: A linear-piecewise function from (0,0) to (1,1). The x values must be in ascending order and between 0 and 1; the y values may be arbitrary. The end values of (0,0) and (1,1) are implicit.
The following easing curves are pre-defined:
Name | Equal to |
---|---|
linear | path() |
ease | cubic-bezier(0.25, 0.10, 0.25, 1.00) |
ease-in | cubic-bezier(0.42, 0.00, 1.00, 1.00) |
ease-out | cubic-bezier(0.00, 0.00, 0.58, 1.00) |
ease-in-out | cubic-bezier(0.42, 0.00, 0.58, 1.00) |
repeatCount
The repeatCount defines how many times an animation will repeat before the command stops. By default, the repeatCount is set to 0; the animation will play through once and stop.
repeatMode
The repeatMode
defines whether animations will be played from start to
finish each time or if the animation will play backwards to the start
each alternative time. The following repeat modes are defined:
Name | Description |
---|---|
restart | The animation starts over from the original value on each repeat. |
reverse | The animation reverses direction each time. |
The end state of an animation is a function of the repeatCount
and
repeatMode
. If the repeatMode
is reverse and the repeatCount
is an odd
number, the animation end state will be the same as its starting state.
In all other cases the end state will be the "natural" end state
assigned as the to
value.
A prematurely stopped animation always "jumps" to its end state.
value
The array of animated properties. Each element in the array has the following form:
Property | Type | Required | Description |
---|---|---|---|
from |
Number | No | The starting value of the property |
property |
String | Yes | The name of the property to animate |
to |
Number | Yes | The ending value of the property |
A property animation is defined by the to/from properties or the inputRange/outputRange properties. If you don't specify a "from" value, the current value of the property is used.
There are a few special cases to consider with the
transform
property.
First, the transform
property
does not implicitly define a from
property; both the from
and to
properties must be set.
Second, interpolating between smoothly between transformations requires
that the same series of transformation operations appear in the from
list and the to
list and in the same order. For example:
"from": [ { "translateX": 30 }, { "rotate": 90 }],
"to": [ { "translateY": 30 }, { "rotate": 45 }]
is a valid from/to
transformation because each array contains a
translation followed by a rotation. A non-working example:
"from": [ { "translateX": 30 }, { "scale": 1 }, { "rotate": 90 }],
"to": [ { "scale": 2 }, { "rotate": 45 }]
In this case the arrays don't match; they have different lengths and
the first element differs between the arrays. The APL author may expect
the system to automatically fill in the "missing"
{ "translateX": 0 }
transformation at the start of the to
array, but
the APL runtime is not clever enough to automatically find and fix the
difference.
AutoPage
The AutoPage
command automatically progresses through a series of pages displayed in a Pager component. The AutoPage
command finishes after the last page has been displayed for the requested time period.
The AutoPage
command has the following properties in addition to the regular command properties.
Property | Type | Default | Description |
---|---|---|---|
componentId | String | SELF | The id of the `Pager` to page through. |
count | Integer | All pages in the pager | The number of pages to display. |
duration | Integer | 0 |
The amount of time (in milliseconds) to wait after advancing to the next page. |
For example, to auto-page through a Pager
called mySportsPager
:
{
"type": "AutoPage",
"componentId": "mySportsPager",
"duration": 1000,
"delay": 500
}
The above example first pauses for 500 milliseconds (the delay
property),
then advances to the next page, pauses for 1000 milliseconds (the duration
property), and continues advancing and pausing until the final pause has
completed. For example, if mySportsPager
has three pages and initially displays page 1, then AutoPage
does the following:
- Displays page 1 for 500ms while waiting to start.
- Changes to page 2 and pauses for 1000ms.
- Changes to page 3 and pauses for 1000ms.
At this point the command is complete, so the Pager
continues to display page 3 until another command or event causes a change.
The AutoPage
command has no effect if the count
is non-positive.
The AutoPage
command does the following when it stops:
- Moves the display ahead to the target page if the
AutoPage
command sequence is at least 50% complete. - Returns the display to the previous page if it is not at least 50% complete.
The onPageChanged
command runs one time with the new page if the page has changed
The AutoPage
command is ignored in fast mode.
componentId
The identifier of the Pager component. If omitted, the component issuing the AutoPage
command is used.
count
The number of pages to display. If not specified, this defaults to the number of pages remaining. Wrapping is not supported; the count is internally clipped to fall in the range [0, pager.children.length - pager.currentIndex - 1].
duration
The amount of time to wait after advancing to the next page. Any animated transition between pages is not included in the duration and therefore increases the overall command run time.
Since the duration is applied after advancing to the next page, it does not apply to the first page of the pager. To delay the start of paging, use the standard command delay
property.
ClearFocus
ClearFocus
requires APL 1.1 or later. Provide an alternate experience for devices running older versions of APL.
Removes focus from the actionable component that is currently in focus. See Focused for the actionable components that can receive and lose focus.
Only one component may have focus at a time, so ClearFocus
only ever
affects one component.
When ClearFocus
runs, the command removes focus from the
component that has it, and sets that component's
focused
state to false
.
The ClearFocus
command has no additional properties to the regular
command properties.
For example, to clear focus from any component that has it:
{
"type": "ClearFocus"
}
The ClearFocus
command runs in fast mode, but without any delay.
Finish
Finish
requires APL 1.3 or later. Provide an alternate experience for devices running older versions of APL.
Closes the current APL document and exits. The finish command has no properties beyond the common command properties.
Running the finish command stops all other processing in APL, including any commands that are still running. For example, if you wish to both use SendEvent and Finish on a button press, you must write them in the following order:
{
"onPress": [
{
"type": "SendEvent",
"arguments": [
"now stopping"
]
},
{
"type": "Finish"
}
]
}
If you write the commands in the reverse order, SendEvent
never runs.
The finish command runs in both normal and fast mode.
Idle
The Idle
command does nothing. Use as a placeholder or to insert a calculated delay in a longer series of commands. For example, consider this command.
{
"type": "Parallel",
"commands": [
{
"type": "Idle",
"delay": 3000
},
{
"type": "SpeakItem",
"componentId": "item7"
}
]
}
This command sequence speaks "item7". The use of the Idle
command guarantees that the overall command will last at least 3000 milliseconds even if the speech ends earlier.
The type
of the Idle
command is Idle
.
The idle command is ignored in fast mode
OpenURL
OpenURL
requires APL 1.1 or later. Provide an alternate experience for devices running older versions of APL.
Open a URL. The OpenURL
command, if successful, opens the specified URL in a web browser or other application on the device. You must provide a suitable URL that works on the current device. The OpenURL
command has the following properties in addition to the regular command properties:
Property | Type | Default | Description |
---|---|---|---|
source | String | REQUIRED | The URL to open. |
onFail | Array of command | [ ] | Command to run if the URL fails to open. |
For example, to open the Amazon home page in the browser on the device:
{
"type": "OpenURL",
"source": "https://www.amazon.com/",
"onFail": {
"type": "SetValue",
"componentId": "errorText",
"property": "text",
"value": "Unable to open Amazon.com (${event.source.value})"
}
}
Not all devices support opening a URL. If the device does not support opening URLs, the command is ignored and it does not run onFail
commands. Check the value of the allowOpenURL
in the data-binding context to determine if OpenURL
is supported on the device.
The OpenURL
command is ignored in fast mode.
source
The source
property is a URL/URI suitable for launching an application
on the local device. It may also be used with the http or https schema
to open a web page in the local web browser.
onFail
The onFail
property contains one or more commands to run if the
URL cannot be opened. There is no guarantee that the onFail
command
will run within a time limit or that it will appear to be successful to
the end user; for example, a URL could open a blank or error web page.
However, the APL runtime should try to report failure within three
seconds. The event generated for the onFail
command has the following
form:
"event": {
"source": {
"source": "OpenURL",
"handler": "Fail",
"value": NUMBER // Platform-defined numerical error
}
}
The event.source.value
field passed to the onFail
command will be
set to a platform-defined numerical error code. This error code is not
suitable for showing to the user (despite the example provided above),
but may be used to send failure information back to the cloud skill
through a SendEvent
command.
Parallel
Run a series of commands in parallel. The Parallel
command starts running all child commands simultaneously. The Parallel
command is considered finished when all of its child commands have finished. When the Parallel
command stops early, all currently running commands stop.
The type
of the Parallel
command is Parallel
. The Parallel
command has the following properties in addition to the common command properties.
Property | Type | Default | Description |
---|---|---|---|
commands | Array of commands | REQUIRED | An unordered list of command to run in parallel |
In fast mode, the parallel command runs all of the sub-commands in parallel, but without delays (giving a net zero duration)
commands
An un-ordered array of commands to run in parallel. Once all commands have finished running, the Parallel
command finishes. The delay
value set for the Parallel
command is added to the delay
value set for each of the commands in the array. In the following example, the first SendEvent
command starts after 1500 milliseconds, and the second SendEvent
command after 750 milliseconds, which means the second SendEvent
command starts before the first.
{
"type": "Parallel",
"delay": 500,
"commands": [
{
"type": "SendEvent",
"delay": 1000
},
{
"type": "SendEvent",
"delay": 250
}
]
}
Reinflate
Reinflates the current document with updated configuration properties. Alexa rebuilds the entire document, following the same process as when initially displaying the document on the screen. Alexa creates a new, updated data-binding context with environment
and viewport
constants that match the new device configuration.
The Reinflate
command has no additional properties.
Running Reinflate
command stops all other processing in APL, including any other commands. For example, if you want to run both SendEvent
and Reinflate
in the same handler, you must put the SendEvent
first.
The following example sends a UserEvent
request to the skill, and then reinflates the document.
{
"onConfigChange": [
{
"type": "SendEvent",
"sequencer": "ConfigSendEvent",
"arguments": [
"reinflating the APL document"
]
},
{
"type": "Reinflate"
}
]
}
If you write the commands the reverse order, the SendEvent
never runs. Note that the SendEvent
needs a sequencer because the onConfigChange
handler runs in fast mode.
The document and component-level onMount
commands run after the document reinflates.
The Reinflate
command runs in both normal and fast mode.
For details about using reinflate to support tablets, see Support Tablets and Other Devices that Can Change Size.
Scroll
The Scroll
command scrolls a ScrollView or Sequence forward or backward by a set number of pages. The Scroll
command has the following properties in addition to the regular command properties.
Property | Type | Default | Description |
---|---|---|---|
componentId | String | SELF | The id of the component to read. |
distance | Number | 1 | The number of pages to scroll. Defaults to 1. |
The distance sets how far to scroll, in pages. For example, to scroll a list forward a single page:
{
"type": "Scroll",
"componentId": "myScrollingList",
"distance": 1
}
Scrolling stops when:
- The destination is reached.
- The end of the scrollable content is reached.
- The user touches the screen.
- Alexa sends a new command. Starting a new command ends the
Scroll
command, which stops scrolling immediately.
To smoothly scroll through all available content, set the distance
to a large number. For example, to smoothly scroll back to the beginning of a list:
{
"type": "Scroll",
"componentId": "myScrollingList",
"distance": -10000
}
The Scroll
command is ignored in fast mode.
componentId
The ID of the ScrollView or Sequence. If omitted, the component issuing the ScrollPage
command is used.
distance
The scrolling distance, measured in pages. One "page" is the width or height
of the ScrollView
or Sequence
, less any applied padding. Negative numbers
scroll backwards. Setting distance
to 0 does not scroll.
For example consider a ScrollView
with a height of 400dp and 50dp of padding
on the top and bottom. A "page" of the ScrollView
is 300dp. Specifying
a distance of 0.5 will scroll forward by 50% of the page, or 150dp.
The distance may also be expressed as a relative or absolute dimension with a suitable suffix; for example, "50%", "33dp", or "25vh". Note that setting the distance to a relative number (e.g. "50%") is exactly equal to using a simple number (in this case, 0.5). Because APL documents are commonly written to adjust to the size of the screen it is preferable to use relative scrolling dimensions such as "50%" or 0.5 over using absolute dimensions such as "100dp". This ensures that the content will scroll a sensible distance for the user no matter what device it is displayed on.
ScrollToComponent
Scroll forward or backward through a ScrollView
or Sequence
to
ensure that a particular component is in view. The ScrollToComponent
command has the following properties in addition to the regular command
properties.
Property | Type | Default | Description |
---|---|---|---|
align |
first , center , last , visible |
visible |
The alignment of the item after scrolling |
componentId |
String | SELF | The id of the component. |
For example, to scroll to ensure a particular item is in view:
{
"type": "ScrollToComponent",
"componentId": "recipeSteps",
"align": "center"
}
The ScrollToComponent
command looks for the first Sequence
or
ScrollView
at or above the componentId
and scrolls that one.
Scrolling stops if the user touches the screen. Stopping the command stops scrolling immediately.
The ScrollToComponent
command is ignored in fast mode.
align
The alignment of the item on the screen after scrolling and before speech. Alignment is an enumerated value with the following options:
Alignment | Description |
---|---|
first |
The top/left side of the item will be placed at the top/left side of the scrolling container. |
center |
The center of the item will be placed in the center of the container. |
last |
The bottom/right side of the item will be placed at the bottom/right side of the scrolling container. |
visible |
The item will be moved the minimal distance necessary to bring it fully into view. |
componentId
The ID of component. If omitted, the component issuing the
ScrollToComponent
command is used.
ScrollToIndex
Scroll forward or backward through a ScrollView or Sequence to ensure that a particular child component is in view. The ScrollToIndex
command has the following properties in addition to the regular command properties.
Property | Type | Default | Description |
---|---|---|---|
align |
first , last , center , visible |
visible |
The alignment of the item after scrolling. |
componentId |
String | SELF | The id of the component to read. |
index |
Integer | REQUIRED | The 0-based index of the child to display. |
For example, to scroll to show the fifth step in a recipe displayed in a
list, set index
to 4.
{
"type": "ScrollToIndex",
"componentId": "recipeSteps",
"index": 4,
"align": "center"
}
The componentId
does not have to be a Sequence
or ScrollView
component. The ScrollToIndex
command looks for the first Sequence
or ScrollView
at or above the componentId
and scrolls that one.
Scrolling stops if the user touches the screen. Stopping the command stops scrolling immediately.
The ScrollToIndex
command is ignored in fast mode.
align
The alignment of the item on the screen after scrolling and before speech. Alignment is an enumerated value with the following options.
Alignment | Description |
---|---|
first | The top/left side of the item will be placed at the top/left side of the scrolling container. |
center | The center of the item will be placed in the center of the container. |
last | The bottom/right side of the item will be placed at the bottom/right side of the scrolling container. |
visible | The item will be moved the minimal distance necessary to bring it fully into view. |
componentId
The identifier of the parent container. If omitted, the component issuing the ScrollToIndex
command is used.
index
The 0-based index of the child item in the parent container to scroll into view. Negative values are measured from the end of the parent container. For example, to show the second-to-last item in a list:
{
"type": "ScrollToIndex",
"index": -2,
}
The algorithm for finding the item to display can be described loosely as follows:
let itemIndex = index < 0 ? index + children.length : index;
if (itemIndex >= 0 && itemIndex < children.length) {
let child = children[itemIndex];
scrollIntoView(child);
}
Select
Select
requires APL 1.3 or later. Provide an alternate experience for devices running older versions of APL.
Select a single command from an array of commands and data. The Select
command has the following properties in addition to the standard command properties:
Property | Type | Default | Description |
---|---|---|---|
commands | Array of Commands | REQUIRED | An ordered list of commands to select from |
data | Array | [] | A list of data to map against the commands |
otherwise | Array of Commands | [] | An array of commands to run if no command is selected from the commands array |
When the data
array is empty, the Select
command runs the first command in the commands
array where when
evaluates to true
.
In this example, assume age
is 7
. The command iterates the commands
array until it reaches the third command. The when
statement for this command evaluates to true
, so Select
runs the SetValue
command and updates the specified text
property to the value "Kid".
{
"type": "Select",
"commands": [
{
"when": "${age < 2}",
"type": "SetValue",
"property": "text",
"value": "Infant",
"componentId": "${textIdToUpdate}"
},
{
"when": "${age < 5}",
"type": "SetValue",
"property": "text",
"value": "Toddler",
"componentId": "${textIdToUpdate}"
},
{
"when": "${age < 13}",
"type": "SetValue",
"property": "text",
"value": "Kid",
"componentId": "${textIdToUpdate}"
},
{
"when": "${age < 18}",
"type": "SetValue",
"property": "text",
"value": "Teen",
"componentId": "${textIdToUpdate}"
},
{
"type": "SetValue",
"property": "text",
"value": "Adult",
"componentId": "${textIdToUpdate}"
}
]
}
When you provide the data
array, the Select
command checks each command in the commands
array for a true when
clause one time per item in the data
array. The data-binding context is extended by binding data
, index
, and length
properties. The Select
command finishes after it runs a single command; it does not continue iterating over the data
array.
In this example, assume age
is 17
. The command iterates through data
array. The when
statement for the command evaluates to true
for the data provided in the fourth item (17 < 18
), so Select
stops iterating through the data array and runs the SetValue
command, which updates the specified text
property to "Your category is Teen".
{
"type": "Select",
"commands": {
"when": "${!data.until || age < data.until}",
"type": "SetValue",
"property": "text",
"value": "Your category is ${data.category}",
"componentId": "${textIdToUpdate}"
},
"data": [
{
"until": 2,
"category": "Infant"
},
{
"until": 5,
"category": "Toddler"
},
{
"until": 13,
"category": "Kid"
},
{
"until": 18,
"category": "Teen"
},
{
"category": "Adult"
}
]
}
You can combine multiple commands
with a data
array. Select
still runs only a single command in the commands
array. For example:
{
"type": "Select",
"commands": [
{
"when": "${searchCategory == data.category && data.rating >= 8.0}",
"type": "SetValue",
"property": "text",
"componentId": "${textIdToUpdate}",
"value": "Here's a great movie for your category: <em>${data.title}</em>"
},
{
"when": "${searchCategory == data.category}",
"type": "SetValue",
"property": "text",
"componentId": "${textIdToUpdate}",
"value": "Here's an okay movie for your category: <em>${data.title}</em>"
}
],
"data": "${movieData}"
}
In this example, movieData
is bound to an array of movies sorted by category and rating, with the highest rated movies first:
{
"movieData": [
{"title":"Avatar","category":"Adventure","rating":7.8},
{"title":"Aladdin","category":"Adventure","rating":7.1},
{"title":"Coco","category":"Animation","rating":8.4},
{"title":"Toy Story 4","category":"Animation","rating":8},
{"title":"The Lion King","category":"Animation","rating":7}
]
}
If SearchCategory
is "Animation", Select
iterates until it reaches the third item in data
, which matches both of the criteria in the first when
statement. The first command then runs and updates the text
property of the movieResultTextComponent
component with the text "Here's a great movie for your category: Coco".
If SearchCategory
is "Adventure", Select
chooses the first item in data
since this item matches the criteria for the second when
statement. The second command then runs and updates the text
property of movieResultTextComponent
to "Here's an okay movie for your category: Avatar".
commands
An array of commands. The first command in the array with a true when
clause runs.
data
The array of data to iterate over. During iteration the data-binding context is extended with the following properties:
Name | Description |
---|---|
data | Data assigned from the data array property |
index | The 0-based index of the current data item |
length | The total number of data items in the data array |
Note that these properties are only set if the data
array property contains at least one item.
otherwise
The otherwise
commands run when none of the commands in the commands
property run. The otherwise
commands do not have access to the data
property. For example:
{
"type": "Select",
"commands": {
"when": "${data.breed == breed}",
"type": "SetValue",
"property": "text",
"componentId": "${textIdToUpdate}",
"value": "Your dog is ${data.description}"
},
"otherwise": {
"type": "SetValue",
"property": "text",
"componentId": "${textIdToUpdate}",
"value": "Your dog is indescribable!"
},
"data": "${dogBreedData}"
}
Contents of the dogBreedData
array:
{
"dogBreedData": [
{
"breed": "Affenpinscher",
"description": "loyal, curious, and amusing"
},
{
"breed": "Bassett Hound",
"description": "endearing with floppy ears"
},
{
"breed": "Beagle",
"description": "happy-go-lucky and cheerful"
}
]
}
In the above example, passing the breed
"Mixed Mutt" falls throught to the otherwise
and updates the provided Text
component text with "Your dog is indescribable!"
The otherwise
property provides fallback behavior for when nothing from the data
array matches.
SendEvent
Use the SendEvent
command to generate and send an event to Alexa. The SendEvent
command sends an Alexa.Presentation.APL.UserEvent
request to your skill. The UserEvent
request includes information about the components and events that triggered the command.
The following example illustrates a SendEvent
command on the onPress
handler of a TouchWrapper
.
{
"type": "TouchWrapper",
"id": "idForTheTouchWrapper",
"spacing": "@spacingSmall",
"alignSelf": "center",
"onPress": [
{
"type": "SendEvent",
"arguments": [
"textWasPressed",
"Send this data to the skill"
],
"components": [
"idForTheTextComponent"
]
}
],
"item": {
"type": "Text",
"id": "idForTheTextComponent",
"color": "@colorAccent",
"text": "Click to send a UserEvent to the skill."
}
}
SendEvent
has the following properties in addition to the regular command properties.
Property | Type | Default | Description |
---|---|---|---|
arguments | Array of objects | [ ] | An array of argument data to send to the skill in the UserEvent request. |
components | Array of strings | [ ] | An array of component IDs. The value associated with each identified component is included in the the resulting UserEvent request. |
The SendEvent
command is ignored in fast mode.
arguments
An array of data to send to the skill in the UserEvent
request. Data binding applies to each element in the array when SendEvent
runs. This allows an argument to contain data about the event itself, such as ${event.source.value}
. Use this to send arbitrary data to your skill.
Access this data in your UserEvent
handler in the arguments
property of the request.
components
The components
property is an array of selector strings. The UserEvent
request includes the value
of each component. For example, you can use the components
property to construct a form that sends the contents of each component to your skill.
The value for a given component depends on the type of component:
- A component with a basic press interaction, such as a
TouchWrapper
, reports thechecked
state of the component. - A rich component that supports interaction, such as a
Pager
,Sequence
, orScrollView
, reports component-specific values. For example, aPager
reports the index of the displayed page. Refer to component documentation for what they report. - Other components report
null
, unless stated otherwise the component documentation.
Access the component values in the components
property of the request.
UserEvent
The SendEvent
command sends the skill an Alexa.Presentation.APL.UserEvent
request.
For example, the SendEvent
defined in the TouchWrapper
shown earlier generates the following UserEvent
request.
{
"type": "Alexa.Presentation.APL.UserEvent",
"requestId": "amzn1.echo-api.request.1",
"timestamp": "2020-01-20T22:28:44Z",
"locale": "en-US",
"arguments": [
"textWasPressed",
"Send this data to the skill"
],
"components": {
"idForTheTextComponent": "Click to send a UserEvent to the skill."
},
"source": {
"type": "TouchWrapper",
"handler": "Press",
"id": "idForTheTouchWrapper"
},
"token": "token-provided-with-RenderDocument"
}
This UserEvent
includes the following information defined in the SendEvent
command:
- The
arguments
property contains an array containing the data passed to thearguments
array of theSendEvent
command. In this example, these are static strings, but you could use data-binding to include dynamic information here. - The
source
property includes details about the component that triggered the event. In this example, this is theTouchWrapper
. - The
components
property contains thevalue
of the component with the ID "idForTheTextComponent
". Since this is aText
component, the value included in theUserEvent
is the value of thetext
property. This is included because theSendEvent
included this same ID in thecomponents
array.
For more details about the UserEvent
request, see UserEvent
request.
For an example of a UserEvent
handler, see Handle a UserEvent request.
Sequential
The Sequential
command runs a series of commands in order, waiting for the previous command to finish before starting the next. The Sequential
command is finished when all of its child commands have finished.
The type
of the Sequential
command is Sequential
. The Sequential
command has the following properties in addition to the common command properties.
Property | Type | Default | Description |
---|---|---|---|
catch |
Array of Commands | [] | An ordered list of commands to run if this sequence stops early. |
commands |
Array of Commands | REQUIRED | An ordered list of command to run in series. |
repeatCount |
Integer | 0 | Additional number of times to run these commands. |
finally |
Array of Commands | [] | An ordered list of commands to run after the normal commands and the catch commands |
- In normal mode the
commands
run in order, followed by thefinally
commands. TherepeatCount
only applies to the regular commands. - In fast mode the
commands
run in order without repeating, followed by thefinally
commands. - If one of the
commands
stops early (in normal mode), thecatch
commands andfinally
commands run in fast mode. - If one of the
finally
commands stops while running in normal mode, the remainingfinally
commands run in fast mode.
catch
catch
requires APL 1.1 or later. Provide an alternate experience for devices running older versions of APL.
The catch commands run if the Sequential
command stops due to another command running. The catch commands run in "fast" mode – that is, all durations are ignored and commands jump to their final values. The catch commands run before any finally
commands.
The catch
commands run one time. The repeatCount
property doesn't apply to catch
commands.
commands
An array of commands to run. The commands run in array order, and each command must finish before the next one can begin. The delay
value of the Sequential
command and the delay
value of the first command in the sequence are additive. In the following example, the first SendEvent
command runs after 3000 milliseconds.
{
"type": "Sequential",
"delay": 1000,
"repeatCount": 2,
"commands": [
{
"type": "SendEvent",
"delay": 2000
},
{
"type": "SendEvent",
"delay": 2000
}
]
}
finally
finally
requires APL 1.1 or later. Provide an alternate experience for devices running older versions of APL.
The finally
commands run after the normal sequential commands finish or after the catch
commands run due to the command stopping early. The finally
commands run in normal mode unless (a) the entire Sequential command ran in fast mode or (b) the sequential command stopped early.
The finally
commands run one time. The repeatCount
property doesn't apply to finally
commands.
repeatCount
The number of times to repeat this series of commands. Defaults to 0. Negative values will be ignored.
SetFocus
SetFocus
requires APL 1.1 or later. Provide an alternate experience for devices running older versions of APL.
Changes the actionable component that is in focus. See Focused for the actionable components that can receive and lose focus.
Only one component has focus at a time. Setting the focus on a component automatically clears it from other components.
When SetFocus
runs, the command does the following:
- Places the targeted component into focus and sets that
focused
state to true. - Removes focus from any component that had it before and sets that component's
focused
state to false.
The SetFocus
command is ignored if the targeted component is disabled, not actionable, or has the inheritParentState
property set to true.
The SetFocus
command has the following properties in addition to the
standard command properties.
Property | Type | Default | Description |
---|---|---|---|
componentId | String | SELF | The id of the component which will receive focus. |
For example, to focus a specific component with the id
myButton
:
{
"type": "SetFocus",
"componentId": "myButton"
}
The SetFocus
command runs in fast mode, but without any delay.
componentId
The ID of the component which will receive focus. If this property is
omitted, the component issuing the SetFocus
command is the recipient.
To open a document with a component in focus, set the document
onMount
property to SetFocus
.
For example, to focus the component with the id
myButton
on document mount:
{
"onMount": {
"type": "SetFocus",
"componentId": "myButton"
}
}
SetPage
The SetPage
command changes the page displayed in a Pager
component. The SetPage
command finishes when the item is fully in view. The SetPage
command has the following properties in addition to the regular command properties.
Property | Type | Default | Description |
---|---|---|---|
componentId |
String | SELF | The id of the component to read. |
position |
relative, absolute | absolute |
Whether the value is a relative or absolute offset. Defaults to absolute . |
value |
Integer | REQUIRED | The distance to move. May be an absolute or relative value. |
When there are N
pages in the Pager component, the first is index 0
and the last has index N-1
. A relative position offsets from the current page. For example, to move one page forward:
{
"type": "SetPage",
"componentId": "myWeatherPager",
"position": "relative",
"value": 1
}
An absolute position sets the index of the current page. A negative absolute position is an offset from the end of the list. For example, to go to the last page:
{
"type": "SetPage",
"componentId": "myWeatherPager",
"position": "absolute",
"value": -1
}
No intermediate pages display when switching between two pages (unlike a Sequence
). For example, if the current page is 13 and SetPage
runs with "position"="relative","value": 2
, the current page transitions out and page 11 displays without showing page 12.
The SetPage
command can set any page for display. It does not respect the allowed navigation direction in the Pager
component. However, wrapping behavior affects page switch calculations, as shown in approximate algorithm.
Stopping a SetPage
command jumps ahead to the target page if the SetPage
command sequence is at least 50% complete, and it returns to the previous page if it is not at least 50% complete. The onPageChanged
command runs one time when the command stops if the page has changed from the last page.
The SetPage
command is ignored in fast mode.
componentId
The identifier of the Pager component. If omitted, the component issuing the
SetPage
command is used.
position
If the position
is relative
, the value
is a relative distance to move from the current page. If the position
is absolute
, the value
is the absolute page number to which the display will move.
value
The value
is either the distance to move or the absolute page number to move to.
The algorithm to calculate final position and direction can be approximated with this pseudo-code.
if (command.position == 'absolute') { // Absolute motion
let index = command.value < 0 ? pager.children.length + command.value : command.value;
index = Math.max(0, Math.min(pager.children.length - 1, index)); // Clamp range
// Return the final index and the direction of motion
if (index == pager.currentIndex)
return NO_MOVE
return (index, index < pager.currentIndex ? "LEFT" : "RIGHT");
}
else { // Relative motion
let index = pager.currentIndex + command.value;
// If relative motion goes out of bounds and we don't support wrapping, ignore the command
if (pager.navigation != "wrap" && (index < 0 || index >= pager.children.length))
return NO_MOVE;
// Wrap appropriately
index = ((index % pager.children.length) + pager.children.length) % pager.children.length;
if (index == pager.currentIndex)
return NO_MOVE;
return (index, command.value < 0 ? "LEFT" : "RIGHT");
}
The pager animation is driven by the returned direction.
This algorithm has these characteristics:
-
Absolute values clamp within the valid range of pages. The
direction
is relative to the current page. -
Relative values on a wrapping pager will wrap arbitrarily. The
direction
is based on the commanded value, and wrapping doesn't change the direction. -
Relative values on a non-wrapping pager that go out of range are ignored.
SetValue
Changes a property or binding of a component. Each component has a defined set of dynamic properties that can be changed with SetValue
. Each component also may have named bindings. Refer to the specifics of each component for the dynamic properties you can change with SetValue
.
The SetValue
command has the following properties in addition to the regular command properties.
Property | Type | Default | Description |
---|---|---|---|
componentId | String | SELF | The id of the component whose value should be set. |
property | String | REQUIRED | The name of the property to set. |
value | String | REQUIRED | The value to set on the property. |
This example sets a value so that the punchline for a joke appears, because an opacity
value of 1 means the component is fully visible.
{
"type": "SetValue",
"componentId": "jokePunchline",
"property": "opacity",
"value": 1
}
The SetValue
command changes the value of a component property or component binding. The following rules are followed:
- If the component has a property named
property
that is dynamic, then the property is updated with the new value. - Otherwise, if the component has a bind property with that name, then that bound property is updated.
- If a bound property changes value, then all dynamic properties of components that depend on that property are updated.
The following example shows how to update a binding value. Click the text in the simulator and note how the number increments each time. Refresh the page or change viewport profiles to reset the counter.
In the above example, each time you press the TouchWrapper
, the text displayed increments.
The SetValue
command runs in fast mode, but without any delay.
componentId
The identifier of the component whose value will change. If this property is omitted, then the component that issues the SetValue
command is the recipient.
property
The name of the property to change. This may be a built-in property or a binding.
value
The value
evaluates when the command runs, so it can take advantage of existing component properties. In this example, the SetValue
command sets the opacity of the target component to 50% of its actual value.
{
"type": "SetValue"
"property": "opacity",
"value": "${event.target.opacity * 0.5}"
}
SpeakItem
The SpeakItem
command reads the contents of a single component on the screen. The component scrolls or pages into view if it isn't already visible.
The SpeakItem
command speaks the content provided in the speech
property for the component. When the component doesn't have a speech
property, the SpeakItem
command scrolls the component into view, but doesn't render any speech.
Set the speech
property of the component to the output of a transformer
that converts to speech, such as the ssmlToSpeech
, textToSpeech
, or aplAudioToSpeech
transformer.
Some environments might not allow dialog, including speech. Use the environment property disallowDialog
to determine whether the device and configuration supports speech-related commands.
The SpeakItem
command has the following properties in addition to the regular command properties.
Property | Type | Default | Description |
---|---|---|---|
align |
first , last , center , visible |
visible |
The alignment of the item after scrolling. Defaults to "visible". |
componentId |
String | SELF | The id of the component to read. |
highlightMode |
line , block |
block | How karaoke is applied: on a line-by-line basis, or to the entire block. Defaults to "block". |
minimumDwellTime |
Integer | 0 | The minimum number of milliseconds that an item will be highlighted. |
The following example shows the SpeakItem
command that reads the contents of a single text component and aligns the text in the center of the screen:
{
"type": "SpeakItem",
"componentId": "myJokeSetup",
"highlightMode": "line",
"align": "center"
}
The SpeakItem
command sets the karaoke
state of the component to true
during the speech and then sets it back to false
after the speech completes. The highlightMode
property applies to Text components. When Alexa reads a Text
component in "highlightMode": "line"
mode, individual lines of text are set to the karaoke
state during speech and reset to false
after speech completes.
Note these restrictions:
- The
SpeakItem
command does not scroll the content during speech inblock
mode. For example, if the component is larger than the scrolling container of the component, those parts of the component that aren't visible after scrolling remain hidden. - Components on round screens should use center alignment, or much of the content won't be visible.
SpeakItem
does not highlight individual words or lines of text during speech whenhighlightMode
isblock
.- The algorithm used to scroll the item into view assumes there is only a single scrolling component. Nested scrolling components aren't supported.
- Components without a
speech
property scroll into view, but do not render any speech. - The
SpeakItem
stops during configuration changes, such switching the orientation on a tablet.
When a SpeakItem
command stops early, it clears any visual changes and stops speech immediately.
The SpeakItem
command is ignored in fast mode.
align
The alignment of the item on the screen after scrolling and before speech. Alignment is an enumerated value with the following options.
Alignment | Description |
---|---|
first | The top/left side of the item will be placed at the top/left side of the scrolling container. |
center | The center of the item will be placed in the center of the container. |
last | The bottom/right side of the item will be placed at the bottom/right side of the scrolling container. |
visible | The item will be moved the minimal distance necessary to bring it fully into view. |
componentId
The ID of the spoken component. If omitted, the component issuing the SpeakItem
command is used.
highlightMode
Controls how contents of a Text
component are styled during speech. If set to "block
", the entire Text
component has the karaoke
state set to true during speech. If highlightMode
is set to "line", the individual lines of the Text
component are treated separately. Each line will scroll to match the align
property and be styled separately.
In line-by-line karaoke mode, the only styling change accepted is the color
property; other properties are ignored.
When a component other than a Text
component is the recipient of SpeakItem
,
the highlightMode
is ignored.
minimumDwellTime
The minimum amount of time in milliseconds to highlight an item.
SpeakList
Read the contents of a range of items inside a common container. Each item scrolls into view before Alexa reads the item. The speech
property on each item defines the speech to play. If an item doesn't have the speech
property set, the item scrolls into view without the accompanying speech.
Some environments might not allow dialog, including speech. Use the environment property disallowDialog
to determine whether the device and configuration supports speech-related commands.
The SpeakList
command has the following properties in addition to the regular command properties.
Property | Type | Default | Description |
---|---|---|---|
align |
first , center , last , visible |
visible |
The alignment of the item. Defaults to visible . |
componentId |
String | SELF | The id of the Sequence or Container (or any other hosting component). |
count |
integer | REQUIRED | The number of children to read. |
minimumDwellTime |
number | 0 | The minimum number of milliseconds that an item will be highlighted for. Defaults to 0. |
start |
integer | REQUIRED | The index of the item to start reading. |
The minimumDwellTime
prevents items with short titles from being read too quickly. For example, a series of movie titles like "Venom", "Fences", and "Dear Zachary: A Letter to a Son About His Father" needs some dwell time for the first two items.
This example reads three components out of the middle of a list and ensures that each aligns in the center of the screen:
{
"type": "SpeakList",
"componentId": "movieList",
"start": 3,
"count": 3,
"minimumDwellTime": 700,
"align": "center"
}
The karaoke
state of the component is set to true
during the speech of each component and reset to false
after that speech completes.
You can use the SpeakList
command with child components:
For multi-child components, the SpeakList
command can also speak the firstItem
and lastItem
properties. When the component has a firstItem
defined, the index of the firstItem
is 0 and the indices of the child components in items
start at 1. When the component doesn't have a firstItem
defined, the indices of the child components in items
start at 0.
Note these characteristics of the SpeakList
command:
- The
SpeakList
command does not scroll the content during speech. For example, if the component is larger than the scrolling container of the component, those parts of the component that are not visible after scrolling will remain hidden. - Components on round screens should use
center
alignment, or much of the content will not be visible. SpeakList
does not highlight individual words or lines of text during speech.- To scroll the item into view, the component hierarchy is searched upwards to find the first ancestor that can be scrolled.
- The algorithm that used to scroll the item into view assumes there is only a single scrolling component. SpeakList does not support nested scrolling components.
- Components without a speech property will still scroll into view.
- Components without a speech property, but with a positive
minimumDwellTime
, will have karaoke set for that time. - Components without a speech property and no
minimumDwellTime
will not have karaoke set.
The SpeakList
command is ignored in fast mode.
align
The alignment of the item on the screen after scrolling and before speech. Alignment is an enumerated value with the following options:
Alignment | Description |
---|---|
first |
The top/left side of the item will be placed at the top/left side of the scrolling container. |
center |
The center of the item will be placed in the center of the container. |
last |
The bottom/right side of the item will be placed at the bottom/right side of the scrolling container. |
visible |
The item will be moved the minimal distance necessary to bring it fully into view. |
componentId
The ID of the parent component. If omitted, the component issuing the SpeakList
command is used.
count
The number of items to speak. The command does not run if the count is less than 1 (no scrolling, no speech). If the count is larger than the number of remaining items in the container, it is trimmed to the maximum number of items that can be spoken from the starting point.
minimumDwellTime
The minimum amount of time in milliseconds that an item will be highlighted (that is, have the karaoke
state set to true
). This defaults to 0.
start
The 0-based index of the first child item in the parent container to scroll into view and speak. Negative values are measured from the end of the parent container. This example the last three items in a list:
{
"type": "SpeakList",
"start": -3,
"count": 3
}
The following algorithm approximates how the reading is done.
let first = start < 0 ? start + children.length : start;
let last = Math.min(first + count, children.length – 1);
first = Math.max(0, first);
for (let index = first ; index <= last ; index++) {
let child = children[index];
scrollIntoView(child);
if (child.speech) {
child.setState("karaoke", true);
speakChildWithMinimumDwell(child, minimumDwellTime);
child.setState("karaoke", false);
}
else if (minimumDwellTime > 0) {
child.setState("karaoke", true);
waitForTimeout(minimumDwellTime);
child.setState("karaoke", false);
}
}
Related topics
Last updated: Nov 28, 2023