APL Conditional Component Inflation


Conditional component inflation determines which components and layouts to inflate in an APL document. For example, the mainTemplate property of an APL document accepts an array of components in the items property, but renders a single component. Conditional component inflation determines which one to inflate. The component inflation algorithms enable lightweight conditional expressions using arrays of components, the when property in primitive components, and data-binding.

Conditional inflation scenarios

Conditional inflation works differently depending on the scenario:

  • Single child – Alexa inflates a single component from an array of possible components.
  • Simple array – Alexa inflates a subset of components from an array of components.
  • Data array – Alexa uses a data array to inflate a set of components.

Single child

With single child inflation, Alexa inflates at most one child component from an array of components. For example, the mainTemplate property in an APL document might have multiple components in the items array, but Alexa inflates a single component from the array.

  • Used by – Components that accept an array of components in items, but inflate a single child. This includes:
    • mainTemplate.items array in a document.
    • User-defined layouts.
    • Components that support a single child component: ScrollView, Frame, and TouchWrapper.
    • Properties on multi-child components that inflate a single child such as firstItem and lastItem.
  • Algorithm – Given an array of components, evaluate the when property of each component in turn. Use first component with a when property that evaluates to true. If no component has a true when property, no component is inflated. Note that if the when property is omitted, it defaults to true.
  • Data-binding – None

Sample single child inflation

In this example, a round viewport inflates the Container, and a rectangular viewport inflates the Frame.

"myLayout": 
{
  "parameters": [
    "title",
    "logo"
  ],
  "item": [
    {
      "when": "${viewport.shape == 'round'}",
      "type": "Container",...
    },
    {
      "type": "Frame",...
    }
  ]
}

Single child inflation and mainTemplate

A common error is to place multiple components in the mainTemplate array. Because the mainTemplate property in an APL document uses single child inflation, the first component where when is true displays, and the other components never display.

The when property defaults to true when not provided. The following example shows this scenario. The second Text component never displays.


To use mainTemplate correctly, use a when clause to make the top-level components conditional. For example, change the first component to include a when property that sometimes evaluates to false. In the following example, the first component displays on round viewports and the second component displays on all other types of viewports:

{
  "when": "${viewport.shape == 'round'}",
  "type": "Text",
  "padding": 20,
  "text": "This is the first child component in <tt>mainTemplate</tt>. It doesn't specify <tt>when</tt>, so <tt>when</tt> defaults to <tt>true</tt>. Therefore, this component always displays."
}

To display multiple components at the same time, you must place them inside a multi-child component such as a Container or Sequence.

Simple array of child components

With simple array inflation, Alexa inflates a subset of components from an array of components. For example, you can pass an array of separate components to a the items property of a Container. Alexa renders each item in the array.

  • Used byMultiple-child components when the data property isn't set:
    • Container
    • GridSequence
    • Pager
    • Sequence
  • Algorithm – Evaluate the when property of each component in the array. If the when clause evaluates to true, inflate the component and add it to the array of children.
  • Data-binding – The index, length, and ordinal (optional) values are bound. See Data-binding.

Use a simple array of items when you have a collection of heterogeneous items to render in a multiple-child component.

The following example passes three components to a Container in the items array. The Text heading is always displayed, an image is displayed when the viewport width is less than the viewport height, and the Text leader is always displayed.

{
  "type": "Container",
  "padding": 20,
  "items": [
    {
      "type": "Text",
      "style": "heading",
      "text": "Mars rover Opportunity is declared dead"
    },
    {
      "type": "Image",
      "when": "${viewport.width < viewport.height}",
      "spacing": "@spacingMedium",
      "height": "25%",
      "width": "90%",
      "scale": "best-fill",
      "alignSelf": "center",
      "source": "https://www.example.com/mars-rover.jpg"
    },
    {
      "type": "Text",
      "style": "textStyleBody",
      "spacing": "@spacingMedium",
      "text": "After fifteen years without any signal, the Mars rover Opportunity has ...}"
    }
  ]
}

The following APL document shows this example. The example uses a placeholder for the image, and moves the text and image source into a separate data source. Select the Mobile Small Portrait viewport to see a case in which the when clause is true. This example also imports the alexa-styles package to standardize the visual presentation.


Data array

With data array inflation, Alexa uses an array of data to inflate a set of components. This method is available for multiple-child components when the data property is set.

  • Used by &ndash Multiple-child components when the data property is set to an array of data:
    • Container
    • GridSequence
    • Sequence
    • Pager
  • Algorithm – Each element in the provided data array is bound in turn to "data" in the data-binding context. For each bound element, use the single child algorithm to find a single component.
  • Data-binding – The data, index, length, and ordinal (optional) values are bound.

See Data binding.

Use the data array approach when you have an array of data that you want to concatenate together and display. You define the set of components to inflate. Alexa renders that set of components for each item in data.

For example, consider displaying the steps in a recipe. You could define a Container with a Text component that displays a single step. Then, pass an array of strings in the data property to provide the steps. Alexa inflates the Text component one time for each string in the data array. The Text component has access to the data, ordinal, and index properties for each item in the array.

{
  "type": "Container",
  "padding": 20,
  "direction": "column",
  "numbered": true,
  "item": {
    "type": "Text",
    "text": "${ordinal}. ${data}",
    "spacing": 20
  },
  "data": [
    "Preheat the oven to 350 degrees F.",
    "Using a mixer, cream the butter and sugar until smooth",
    "With the mixer on, add one egg at a time to the butter-sugar mixture and beat until smooth",
    "Combine the flour, baking powder, and salt in a separate ...."
  ]
}

The following APL document shows this Container example in a document. The list of recipe steps are in an array in the data source.


You can also use data array inflation combined with the when property to inflate a heterogeneous set of data. In the following example, the items array for the Sequence contains two components: a Text component and a Container. The Text component uses the when property to display for each data item that has the header property. The Container displays for the data items without this property.

{
  "type": "Sequence",
  "height": "100%",
  "numbered": true,
  "padding": 20,
  "items": [
    {
      "when": "${data.header}",
      "type": "Text",
      "text": "${data.header}",
      "numbering": "reset",
      "fontWeight": "bold"
    },
    {
      "type": "Container",
      "direction": "row",
      "alignItems": "center",
      "items": [
        {
          "type": "Image",
          "source": "${data.url}"
        },
        {
          "type": "Text",
          "text": "${ordinal}. ${data.caption}",
          "spacing": 20
        }
      ]
    }
  ],
  "data": [
    {
      "header": "Beach Photos"
    },
    {
      "url": "https://images.example.com/photos/248797/xxx.jpg",
      "caption": "Scene 248797"
    },
    {
      "url": "https://images.example.com/photos/237739/yyy.jpg",
      "caption": "Beach Boat Clouds Daylight 237739"
    },
    {
      "header": "Dog Photos"
    },
    {
      "url": "https://images.example.com/photos/356378/zzz.jpg",
      "caption": "Adorable Animal Breed Canine 356378"
    }
  ]
}

The following document shows this example. Note that the example uses image placeholders instead of actual images. The example also moves the data array to the data source.



Was this page helpful?

Last updated: Nov 28, 2023