This repository has been archived by the owner on May 10, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
Common Usage
Harry Park edited this page Jul 21, 2020
·
15 revisions
JSX for APL enables developers to use React components to model their responses. It does so by using JSX and React’s render lifecycle to attach Alexa.Presentation.APL.RenderDocument
directive to the responseBuilder object.
Following code shows how the APL document can seamlessly fit into the LaunchIntent handler.
// MainSkill.js
import * as Alexa from 'ask-sdk';
import { LaunchIntentHandler } from './handlers/LaunchIntentHandler';
const builder = Alexa.SkillBuilders.custom();
const handler = builder.addRequestHandlers(
new LaunchIntentHandler()
).lambda();
module.exports = { handler };
// handlers/LaunchIntentHandler.jsx
import * as Alexa from 'ask-sdk';
import * as React from "react";
import { LaunchApl } from './apl/LaunchApl';
import { AplDocument } from 'ask-sdk-jsx-for-apl';
class LaunchIntentHandler {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
}
handle(handlerInput) {
const responseBuilder = handlerInput.responseBuilder;
//React Component render cycle is triggered via getDirective method of AplDocument
return responseBuilder
.addDirective(new AplDocument(<LaunchApl />).getDirective())
.speak("Welcome to my first JSX for APL skill")
.getResponse();
}
};
module.exports = { LaunchIntentHandler };
// apl/LaunchApl.jsx
import * as React from 'react';
import { APL, MainTemplate, Frame, Container, Text } from 'ask-sdk-jsx-for-apl';
//React Component of LaunchIntent APL
export class LaunchApl extends React.Component {
constructor(props) {
super(props);
this.launchMessage = 'Welcome to my first ask-sdk-jsx-for-apl skill!';
}
render() {
return (
<APL theme="dark">
<MainTemplate>
<Frame
width="100vw"
height="100vh"
backgroundColor="rgb(22,147,165)"
>
<Container
alignItems="center"
justifyContent="spaceAround"
>
<Text
text={this.launchMessage}
fontSize="50px"
color="rgb(251,184,41)"
/>
</Container>
</Frame>
</MainTemplate>
</APL>
);
}
}
The following output shows the directive generated by using the above react component.
// Alexa.Presentation.APL.RenderDocument JSON Response
{
"type": "Alexa.Presentation.APL.RenderDocument",
"document": {
"type": "APL",
"version": "1.3",
"import": [],
"theme": "dark",
"mainTemplate": {
"parameters": [],
"items": [
{
"items": [
{
"items": [
{
"items": [],
"text": "Welcome to my first ask-sdk-jsx-for-apl skill!",
"fontSize": "50px",
"color": "rgb(251,184,41)",
"type": "Text"
}
],
"alignItems": "center",
"justifyContent": "spaceAround",
"type": "Container"
}
],
"width": "100vw",
"height": "100vh",
"backgroundColor": "rgb(22,147,165)",
"type": "Frame"
}
]
}
}
}
The following example shows a usage of dynamic APL Response to check for the viewport shape on runtime and service different width and height values for the APL documents.
// LaunchIntentHandler.jsx
import * as React from 'react';
import * as Alexa from 'ask-sdk-core';
import { LaunchApl } from './apl/LaunchApl';
class LaunchIntentHandler {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
}
handle(handlerInput) {
const responseBuilder = handlerInput.responseBuilder;
const viewportShape = handlerInput.requestEnvelope.context.Viewport.shape;
const aplParameters = {
width: '100vw',
height: '100vh'
};
if (viewportShape === 'ROUND') {
aplParameters.width = '80vh';
aplParameters.height = '80vh';
}
//Provide parameters to LaunchApl component.
const LaunchAplDocument = new AplDocument(
<LaunchApl aplParameters={aplParameters}/>
).getDirective();
return responseBuilder
.addDirective(LaunchAplDocument)
.speak("Welcome to my first ask-sdk-jsx-for-apl skill")
.getResponse();
}
};
// apl/LaunchApl.jsx
import * as React from 'react';
import { APL, MainTemplate, Frame, Container, Text } from 'ask-sdk-jsx-for-apl';
export class LaunchApl extends React.Component {
constructor(props) {
super(props);
this.launchMessage = 'Welcome to my first ask-sdk-jsx-for-apl skill!';
}
render() {
//width and height parameters are provided from calling elements.
return (
<APL theme="dark">
<MainTemplate>
<Frame
width={this.props.aplParameters.width}
height={this.props.aplParameters.height}
backgroundColor="rgb(22,147,165)"
>
<Container
alignItems="center"
justifyContent="spaceAround"
>
<Text
text={this.launchMessage}
fontSize="50px"
color="rgb(251,184,41)"
/>
</Container>
</Frame>
</MainTemplate>
</APL>
);
}
}
The best way to make an APL component more maintainable and controllable is to break it into multiple components.
The following example shows the reuse of Container component to serve different content.
// apl/WorkoutApl.jsx
import * as React from 'react';
import { APL, Container, Image, Text } from 'ask-sdk-jsx-for-apl';
import WorkoutColumn from './workout-column-apl';
class WorkoutApl extends React.Component {
private renderWorkoutPartsImage() { ... }
private renderWorkoutStepsImages() { ... }
private renderWorkoutStepsTexts() { ... }
render() {
return (
<APL theme="dark">
<MainTemplate>
<Container width="100%" height="80vh" direction="row">
<WorkoutColumn>
{
this.renderWorkoutPartsImage();
}
</WorkoutColumn>
<WorkoutColumn>
{
this.renderWorkoutStepsImages();
}
</WorkoutColumn>
<WorkoutColumn>
{
this.renderWorkoutStepsTexts();
}
</WorkoutColumn>
</Container>
</MainTemplate>
</APL>
);
}
}
export default WorkoutApl;
// apl/WorkoutColumn.jsx
import * as React from 'react';
import { Container } from 'ask-sdk-jsx-for-apl';
class WorkoutColumn extends React.Component {
render() {
return (
<Container width="30%" height="100%"
paddingBottom="16dp"
paddingLeft="16dp"
paddingRight="16dp"
paddingTop="16dp"
spacing="16dp">
{this.props.children}
</Container>
);
}
}
export default WorkoutColumn;