APL User-defined Commands
You can define custom commands in your Alexa Presentation Language (APL) document or package.
Overview of user-defined commands
The commands property in the APL document defines a set of commands. A user-defined command can call other APL standard commands.
The following example creates a command called slideInFromRight that calls the AnimateItem command.
{
"commands": {
"slideInFromRight": {
"parameters": [
"distance",
{
"name": "duration",
"type": "number",
"default": 300
}
],
"command": {
"type": "AnimateItem",
"easing": "ease-in-out",
"duration": "${duration}",
"value": [
{
"property": "opacity",
"from": 0,
"to": 1
},
{
"property": "transform",
"from": {
"translateX": "${distance}"
},
"to": {
"translateX": 0
}
}
]
}
}
}
}
To use a parameterized command, pass the name of the command as the type.
{
"type": "TouchWrapper"
"onPress": {
"type": "slideInFromRight",
"duration": 1000,
"distance": "20vw"
}
}
In this example, the distance parameter is bound to 20vw in the translateX property animation. The duration of the command is 1000 milliseconds because the value 1000 passed in the duration parameter overrides the default 300 value defined in the command.
Because the command defines a default for duration, you could call this command without providing the duration parameter and get the 300 millisecond animation instead. In contrast, the distance parameter doesn't have a default. If you call the command without distance, the transform.translateX property in the animation defaults to zero, so the "slide" animation is from zero to zero and the component doesn't move.
Command definitions
The command property in the document is a map of command name to a command definition. The command definition contains the following properties:
| Property | Type | Required | Description |
|---|---|---|---|
parameters |
Array of parameter definitions | No | Optional named parameters to add to the data-binding context |
command, commands |
Array of commands | Yes | The array of commands to run |
description |
String | No | Description of this command |
commands
The command property is an implicit sequential block of commands to run. The array of commands supports the standard data-binding with array rules including automatic conversion of a single command into an array of commands and substitution of parameters into the array.
parameters
The parameters are named values that can be passed as arguments. Each parameter is an object with the following properties:
| Property | Type | Required | Description |
|---|---|---|---|
default |
Any | No | The default value to apply if this parameter isn't specified. Defaults to empty. |
description |
String | No | A user-provided description of this parameter |
name |
String | Yes | The parameter name |
type |
any, array, boolean, color, dimension, integer, map, number, object, string |
No | The type of the parameter. Defaults to any |
The parameter name must be a unique name starting with an upper- or lower-case letter and containing no white space ([a-zA-Z][a-zA-Z0-9]*).
As a convenience, a simple parameter name can be used instead of the parameter object (for example, "title" instead of { "name": "title", ... }. This isn't recommended, but does allow compact command definition for cases where no type coercion or defaults values are required.
Command inflation
Commands are inflated with the following algorithm:
- Each
parameteris evaluated and added to the data-binding context. - The
commandarray is evaluated. - Properties assigned to the object but not matching a named parameter are passed to each command as properties.
For example, note this definition of customPressHandler:
"commands": {
"customPressHandler": {
"description": "Hide the current component and fire an event if checked."
"parameters": [
"onChecked",
{
"type": "number",
"name": "opacity",
"default": 0.5
}
],
"commands": [
{
"type": "SetValue",
"property": "opacity",
"value": "${opacity}"
},
{
"type": "Sequential",
"when": "${event.target.checked}",
"commands": [
"${onChecked}"
]
}
]
}
}
Now assume this custom command is invoked with:
{
"onPress": {
"type": "customPressHandler",
"onChecked": {
"type": "SendEvent",
"arguments": ["It was checked!"]
},
"delay": 500
}
}
When the onPress handler fires, the inflated command representation is:
[
{
"type": "SetValue",
"property": "opacity",
"value": 0.5,
"delay": 500
},
{
"type": "Sequential",
"when": "${event.target.checked}",
"delay": 500,
"commands": [
{
"type": "SendEvent",
"arguments": ["It was checked!"]
}
]
}
]
Note the following:
- The original invocation passed a
delayvalue of 500. ThecustomPressHandlerdefinition doesn't includedelayas a parameter, so thedelayvalue was passed into each of the commands in the custom command. - The original invocation didn't pass an
opacityvalue, butopacityis defined as a parameter incustomPressHandler. So the data-binding context was extended by the default value ofopacity, which is 0.5 in this example. That value was used in theSetValuecommand expansion of${opacity}.
Nested Expansion of User Commands
You can define user commands that reference other user commands. For example:
{
"SoftStagger": {
"description": "General soft-stagger sliding objects from the left or right",
"parameters": [
"delay",
"duration",
"distance"
],
"commands": [
{
"type": "SetValue",
"property": "opacity",
"value": 0
},
{
"type": "AnimateItem",
"values": [
{
"property": "opacity",
"to": 1
},
{
"property": "translateX",
"from": "${distance}",
"to": 0
}
],
"delay": "${delay}",
"duration": "${duration}",
"easing": "ease-out"
}
]
}
}
You can use the SoftStagger command as is and pass in the parameters for
delay, duration, and distance. You can also use SoftStagger
to define some standard variations for convenience:
{
"SoftStagger1": {
"commands": {
"type": "SoftStagger",
"delay": 0,
"duration": 666,
"distance": 40
}
},
"SoftStagger2": {
"commands": {
"type": "SoftStagger",
"delay": 50,
"duration": 666,
"distance": 40
}
}
}
You can then add a soft stagger entrance animation to a component with a line like this: onMount:{"type": "SoftStagger2"}.
Last updated: Jan 03, 2025