APL Layout (APL 1.6 to 2023.3)
An Alexa Presentation Language (APL) layout combines components and other layouts into a reusable "custom component". Similar to the way a function in a programming language is a self-contained module of code that takes in arguments and performs a specific task, a layout is a self-contained module of APL code that can take in arguments and render a specific visual element.
Inflating an APL layout is conditional, as different components can be inflated based on the current data-binding context.
About layouts
You define layouts in the layouts
property of an APL document or package. This property takes a string/object map. The layout definition can include an array of parameters
. When you use the layout, you can pass in arguments in these parameters. For example, a layout that displays text within a box with a border might use parameters to specify the text to display and the border color.
For example, consider a HeaderLayoutExample
layout that accepts two parameters: title
and logo
. Within the layout, a Text
component uses the value provided in the title
parameter and an Image
component uses the value provided in the logo
parameter.
The HeaderLayoutExample
layout inflates into a column-based Container
on a round viewport and places the logo before the title. The layout inflates into a row-based Container
on a rectangular viewport, which places the logo after the title on the same row.
The following example shows the APL code for HeaderLayoutExample
.
{
"layouts": {
"description": "A basic header with a title and a logo",
"parameters": [
{
"name": "title",
"type": "string",
"default": "Provide the title to display"
},
{
"name": "logo",
"type": "string"
}
],
"items": [
{
"when": "${viewport.shape == 'round'}",
"type": "Container",
"direction": "column",
"alignItems": "center",
"padding": [64,48],
"items": [
{
"type": "Image",
"source": "${logo}",
"height": 50,
"width": 50
},
{
"type": "Text",
"text": "${title}",
"style": "textStylePrimary"
}
]
},
{
"type": "Container",
"direction": "row",
"padding": [64,32],
"width": "100%",
"justifyContent": "spaceBetween",
"items": [
{
"type": "Text",
"text": "${title}",
"width": "90%",
"style": "textStylePrimary"
},
{
"type": "Image",
"source": "${logo}",
"height": 50,
"width": 50
}
]
}
]
}
}
To invoke the layout in your document, use the layout name for the component type
and then pass in the parameters. The following example shows how you invoke the HeaderLayoutExample
layout.
{
"mainTemplate": {
"parameters": [
"payload"
],
"items": [
{
"type": "HeaderLayoutExample",
"title": "This is the text to use for the title",
"logo": "https://d2o906d8ln7ui1.cloudfront.net/images/cheeseskillicon.png"
}
]
}
}
The following APL document defines the HeaderLayoutExample
layout and displays it on the viewport.
Layout properties
A layout object has the properties shown in the following table.
Property | Type | Required | Description |
---|---|---|---|
|
Array of Binding |
No |
Expressions to add to the data-binding context. |
|
String |
No |
Provides a description of this layout. |
|
Array of Component |
Yes |
The component to inflate. When |
|
Array of parameters |
No |
An array of parameters you can pass to this layout. |
bind
bind
property in layouts requires APL 1.6 or later. Provide an alternate experience for devices running older versions of APL.The bind property of a layout extends the data-binding context for the layout and its children. Each binding object in the binding array contains the following:
Property | Type | Default | Description |
---|---|---|---|
|
String |
Yes |
The name to use for this binding. Must be a valid name. |
|
Any |
Required |
The value to assign to this binding. |
|
|
|
Data type for the binding value. |
The bind
property evaluates after the parameters
property. Bindings are added to the data-binding context in array order. A binding defined later in the array can use the results from bindings defined earlier in the array.
In the following example, Salutation
depends on the FormalName
binding, which in turn depends on the parameters Title
and LastName
.
{
"MyLayout": {
"parameters": [
{"name":"Title","default":"Dr."},
{"name":"FirstName"},
{"name":"LastName"}
],
"bind": [
{"name":"FormalName","value":"${Title} ${LastName}"},
{"name":"Salutation","value":"Dear ${FormalName}"}
]
}
}
To ensure that the bindings you define don't conflict with component property names, capitalize your binding variable names. As shown in the previous example, use Title
instead of title
.
Primitive APL components also support binding local variables. See the bind
property.
item, items
The item
property is either a single component or, if items
, an array of components. Other layouts can also be part of the items
, provided they have already been imported or defined earlier in the layouts
object. See Data-binding evaluation.
When items
contains an array, the layout inflates the first component where the when
condition is true
.
parameters
The parameters are named values that you pass a layout when invoking it. Each parameter is an object with the properties shown in the following table.
Property | Type | Required | Description |
---|---|---|---|
|
Any |
No |
The default value to apply if this parameter is not specified. Defaults to empty. |
|
String |
No |
An optional description that explains the purpose of this parameter. |
|
String/etc |
Yes |
The unique parameter name. Names must start with an upper-case or lower-case letter and can't contain white space. |
|
Type |
No
` The type of the parameter. Defaults to |
For convenience, you can use a simple parameter name instead of the parameter object. For example, define the parameter as title
instead of { "name": "title", ... }
. This allows for more compact code when you don't need default values or type coercion for the values you pass to the parameter. Using the full parameter object is recommended for clarity.
Layout inflation
APL uses the following algorithm to inflate a layout:
- Evaluate each parameter and add the parameter to the data-binding context.
- Evaluate the
item
oritems
property using the single child inflation algorithm. - Pass any properties assigned to the layout, but not matching a named parameter, item, or type to the item for evaluation.
For example, the following code defines a layout that displays text differently for landscape viewports and non-landscape viewports.
"myLayout": {
"parameters": [
"title",
"subtitle"
],
"item": [
{
"when": "${viewport.width > viewport.height}",
"type": "Text",
"text": "<b>${title}:</b> ${subtitle}",
"style": "textStyleDisplay1"
},
{
"type": "Text",
"text": "<b>${title}</b><br>${subtitle}",
"style": "textStyleDisplay2"
}
]
}
The following example invokes this layout and passes in three parameters: title
, subtitle
, and color
. The color
parameter isn't specified as a property in myLayout
.
{
"type": "myLayout",
"title": "Frankenstein",
"subtitle": "or, The Modern Prometheus",
"color": "green"
}
Assume the user's device has a landscape screen. The inflation logic does the following:
- Add the
title
andsubtitle
parameters to the data-binding context. - Evaluate the
item
property and find the first component where thewhen
condition evaluates totrue
. Because the user's device has a landscape screen, APL selects thefirst
component in theitems
array. - Pass any extra properties to the selected
item
. This example passed acolor
property to the layout, which doesn't match any of the defined properties formyLayout
. Therefore, pass this property on to the selected item.
The net result is a Text
component that looks like the following.
{
"type": "Text",
"text": "<b>Frankenstein</b>: or, the Modern Prometheus",
"style": "textStyleDisplay1",
"color": "green"
}
The following APL document defines and displays the myLayout
example. Because color
is a valid property for a Text
component, the Text
component overrides the color
property defined in the style and displays green text. Remove the "color": "green"
line and note that the text color reverts to the color defined in the textStyleDisplay
style.
Related topics
Last updated: Nov 28, 2023