APL Bound Variables


All Alexa Presentation Language (APL) components, layouts, and Alexa Vector Graphics (AVG) support bound variables. A bound variable is a local variable that your document can access from the data-binding context of the component and its children. For a layout, the bound variable is attached to the component that the layout inflates into.

Use the bind property to define a bound variable on a component, layout, or vector graphic. The bind property accepts an ordered array of binding objects that extend the data-binding context.

Evaluation of the bind property

The bind property evaluates after the when property and before any other properties on the component, layout, or AVG. Bindings are added to the data-binding context in array order. A later binding can use previous bindings in its definition, as shown in the following example.

{
  "type": "Text",
  "bind": [
    { "name": "FirstName", "value": "Jasmine" },
    { "name": "LastName", "value": "Smith"},
    { "name": "Title", "value": "Dr."},
    { "name": "FormalName", "value": "${Title} ${LastName}" }
  ],
  "text": "Should I call you ${FirstName} or ${FormalName}?"
}

In this example, FormalName depends upon the earlier definitions of Title and LastName. The final text is "Should I call you Jasmine or Dr. Smith?" This example is contrived. In actual use, you would likely bind the values of FirstName, LastName, and Title to elements provided in the raw data.

You can change binding values dynamically with the SetValue command.

Bind object properties

Each object in the bind array contains the following properties.

Property Type Default Description

name

String

Required

Name to use for this binding. Must be a valid name. You use this name to refer to the variable in data-binding expressions.

value

Any

Required

Value to assign to this binding. When the value is a string, data binding evaluation processes contents of the string.

type

Type

any

Type of value to store in the binding.
Accepted values: any, boolean, string, number, dimension, color

onChange

Array of commands

[]

Commands to run when this binding changes value. Not available in AVG bind properties. Requires APL 2024.1 or later.

name

The name to use for this binding. The name must be valid data binding identifier.

type

The data type for this binding. The default type is any, which means that you can set the value to anything. Specify a type to coerce the binding into that type.

In the following example, the value of Test is true because the variable is a boolean and 23.4 is a non-zero number.

{
  "name": "Test",
  "value": 23.4,
  "type": "boolean"
}

For more about how data binding coerces values into different types, see Truthy and coercion.

value

The value to assign to the binding. This value is coerced to the specified type if necessary. This assignment is evaluated when the binding is first created and whenever any variable used within the binding changes.

The following example defines two bound variables, COUNT and STRING.

{
  "bind": [
    {
      "name": "COUNT",
      "value": 1
    },
    {
      "name": "STRING",
      "value": "The count is ${COUNT}"
    }
  ]
}

Each time the bound value COUNT changes, such as with the SetValue command, the bound value STRING updates as well.

onChange

Requires APL 2024.1 or later.

The onChange event handler runs when the bound value changes in a component or layout. The onChange event handler isn't available in AVG items.

The onChange handler runs in fast mode. The event generated has the following form.

{
  "event": {
    "source": {
      "type": "COMPONENT_TYPE",     // The type of the component or AVG item, such as "Pager", or "TouchWrapper"
      "handler": "Change"
    },
    "current": "VALUE",             // The current value of the binding
    "previous": "VALUE"             // The previous value of the binding
  }
}

A common use of the onChange event handler is to respond to changes in live data provided by an extension. For example if the FishFeeder extension provides a live data object named TankTemperature, then you can use an onChange handler to track the minimum and maximum fish tank temperatures.

{
  "type": "Text",
  "bind": [
    {
      "name": "MIN_TEMP",
      "value": null
    },
    {
      "name": "MAX_TEMP",
      "value": null
    },
    {
      "name": "TEMP",
      "value": "${TankTemperature}",
      "onChange": [
        {
          "type": "SetValue",
          "property": "MIN_TEMP",
          "value": "${MIN_TEMP == null || TEMP < MIN_TEMP ? TEMP : MIN_TEMP}"
        },
        {
          "type": "SetValue",
          "property": "MAX_TEMP",
          "value": "${MAX_TEMP == null || TEMP > MAX_TEMP ? TEMP : MAX_TEMP}"
        }
      ]
    }
  ],
  "text": "Current Temperature=${TEMP} Low=${MIN_TEMP} High=${MAX_TEMP}"
}

For details about live data in extensions, see Extension live data.

The onChange event handler isn't re-entrant. If a command in the onChange handler changes the value of the binding that triggered the onChange handler, the onChange handler isn't called again.

The following example shows a TouchWrapper component with a COUNTER bound variable.

{
  "type": "TouchWrapper",
  "bind": [
    {
      "name": "COUNTER",
      "value": 0,
      "onChange": {
        "type": "SetValue",
        "property": "COUNTER",
        "value": "${COUNTER+1}"
      }
    ]
  },
  "onPress": {
    "type": "SetValue",
    "property": "COUNTER",
    "value": 1
  }
}

Tapping the TouchWrapper sets COUNTER to 1, and the triggers the onChange event handler, which sets the COUNTER to 2. At this point, the command stops because you can't trigger the onChange event handler from within itself.

Bound variable example

The following example displays a counter with buttons to increment and decrement the count. A bound variable called COUNTER stores the current value of the counter and uses onChange to update a Text component each time the value changes. The onChange handler also runs commands to change the color of the counter based on whether it's positive, negative, or zero.



Was this page helpful?

Last updated: Feb 14, 2024