AWS App Studio is in preview and is subject to change.
Using JavaScript to write expressions in App Studio
In AWS App Studio, you can use JavaScript expressions to dynamically control
the behavior and appearance of your applications. Single-line JavaScript expressions are written
within double curly braces, {{ }}
, and can be used in various contexts such as automations, UI components,
and data queries. These expressions are evaluated at runtime and can be used to perform calculations,
manipulate data, and control application logic.
App Studio provides native support for three JavaScript open source libraries: Luxon, UUID, Lodash as well as SDK integrations to detect JavaScript syntax and type-checking errors within your app's configurations.
Basic syntax
JavaScript expressions can include variables, literals, operators, and function calls. Expressions are commonly used to perform calculations or evaluate conditions.
See the following examples:
{{ 2 + 3 }}
will evaluate to 5.{{ "Hello, " + "World!" }}
will evaluate to "Hello, World!".{{ Math.max(5, 10) }}
will evaluate to 10.{{ Math.random() * 10 }}
returns a random number (with decimals) between [0-10).
Interpolation
You can also use JavaScript to interpolate dynamic values within static text. This is achieved by enclosing the JavaScript expression within double curly braces, like the following example:
Hello {{ currentUser.firstName }}, welcome to App Studio!
In this example, currentUser.firstName
is a JavaScript expression that retrieves the first name of the current user,
which is then dynamically inserted into the greeting message.
Concatenation
You can concatenate strings and variables using the +
operator in JavaScript, as in the following example.
{{ currentRow.FirstName + " " + currentRow.LastName }}
This expression combines the values of currentRow.FirstName
and currentRow.LastName
with a space in between,
resulting in the full name of the current row.
Date and time
JavaScript provides various functions and objects for working with dates and times. For example:
{{ new Date().toLocaleDateString() }}
: Returns the current date in a localized format.{{ DateTime.now().toISODate() }}
: Returns the current date in YYYY-MM-DD format, for use in the Date component.
Code blocks
In addition to expressions, you can also write multi-line JavaScript code blocks. Unlike expressions, code blocks do not require curly braces. Instead, you can write your JavaScript code directly within the code block editor.
Note
While expressions are evaluated and their values are displayed, code blocks are run, and their output (if any) is displayed.
Global variables and functions
App Studio provides access to certain global variables and functions that can be used within your
JavaScript expressions and code blocks. For example, currentUser
is a global variable that represents the
currently logged-in user, and you can access properties like currentUser.role
to retrieve the user's role.
Accessing UI component values
One of the powerful features of App Studio is the ability to access values from UI components within expressions. This allows for dynamic behavior and data binding between components, which builders can use to create truly interactive and data-driven applications.
The ui
namespace provides read-only access to the values and properties of UI components on the same page.
By referencing a component's name, you can retrieve its value or perform operations based on its state.
The following list contains the syntax for using the ui
namespace to access UI component values.
{{ui.
: Retrieve the value of a text input component namedtextInputName
.value}}textInputName
.{{ui.
: Check if all fields in the form namedformName
.isValid}}formName
are valid.{{ui.
: Access the value of a specific column in the current row of a table component namedtableName
.currentRow.columnName}}tableName
.{{ui.
: Retrieve the selected rows in a table component namedtableName
.selectedRows}}tableName
.
For example:
{{ui.
gives you the current value of a text input field namedmyTextField
.value}}myTextField
.{{ui.
will check if all fields in a form nameduserForm
.isValid}}userForm
are valid.{{ui.
will retrieve the value of theordersTable
.currentRow.orderTotal
}}orderTotal
column in the current row of a table component namedordersTable
.
However, to update or manipulate the value of a component, you need to use RunComponentAction
. Within expressions,
component values are read-only, but you can trigger actions that modify their values.
Here's an example of how you can update the value of a text input component named myInput
using RunComponentAction
:
RunComponentAction(ui.
myInput
, "setValue", "New Value
")
In this example, the RunComponentAction
step calls the setValue
action on the myInput
component, passing in the new value, New Value
.
By combining the ability to read component values within expressions and update them
using RunComponentAction
steps, you can create dynamic and interactive user interfaces that respond to user input and data changes.
Note that the ui
namespace will only show components on the current page, as components are scoped to their respective pages.
Additional examples
{{ui.
: Check if the value of theinputText1
.value.trim().length > 0}}inputText1
component, after trimming any leading or trailing whitespace, has a non-empty string. This can be useful for validating user input or enabling/disabling other components based on the input text field's value.{{ui.
: For a multi-select component namedmultiSelect1
.value.join(", ")}}multiSelect1
, this expression converts the array of selected option values into a comma-separated string. This can be helpful for displaying the selected options in a user-friendly format or passing the selections to another component or automation.{{ui.
: This expression checks if the valuemultiSelect1
.value.includes("option1
")}}option1
is included in the array of selected options for themultiSelect1
component. It returns true ifoption1
is selected, and false otherwise. This can be useful for conditionally rendering components or taking actions based on specific option selections.{{new Date().toLocaleDateString()}}
: This expression gets the current date and converts it to a localized string representation based on the user's locale settings. It can be used to display the current date in a user-friendly format or to pre-fill date fields with the current date.{{new Date().toISOString()}}
: This expression generates the current date in the ISO format ("2023-06-15T10:30:00.000Z"
), which is the format expected by many entities and components. It can be used to pre-fill date fields with the current date or timestamp.{{ui.
: For an Amazon S3 file upload component nameds3Upload1
.files.length > 0}}s3Upload1
, this expression checks if any files have been uploaded by checking the length of the files array. It can be useful for enabling/disabling other components or actions based on whether files have been uploaded.{{ui.
: This expression filters the list of uploaded files in thes3Upload1
.files.filter(file => file.type === "image/png
").length}}s3Upload1
component to only include PNG image files, and returns the count of those files. This can be helpful for validating or displaying information about the types of files uploaded.
Working with table data
The currentRow
and ui.
objects provide
access to table data, allowing builders to perform operations and manipulations based on the current or selected row.tableName
.selectedRow
Note that currentRow
and ui.
have different structures.
The tableName
.datacurrentRow
object is based on the column mappings configured for the table, while
ui.
contains the raw data from the entity.tableName
.data
The following list contains the syntax for working with table data.
{{currentRow.
: Retrieve the value of thecolumnMappingName
}}columnMappingName
column for the current row in a table.{{ui.
: Retrieve the value of thetableName
.selectedRow.columnMappingName
}}columnMappingName
column for the selected row in the table namedtableName
.
See the following examples:
{{currentRow.
: Concatenate values from multiple columns to create a new column in a table.firstName
+ ' ' + currentRow.lastNamecolumnMapping
}}{{ { "Blocked": "🔴", "Delayed": "🟡", "On track": "🟢" }[currentRow.
: Customize the display value of a field within a table based on the stored status value.statuscolumnMapping
] + " " + currentRow.statuscolumnMapping
}}{{currentRow.
: Pass the referenced row's context within a row action.colName
}} or {{currentRow["First Name
"]}} or {{currentRow}} or {{ui.tableName
.selectedRows[0]}}{{ui.
: Reference the selected row's column name from other components or expressions on the same page.tableName
.selectedRows[0].columnMappingName
}}
Accessing automations
Automations allow you to run server-side logic and operations in App Studio. You can use expressions to process data, generate dynamic values, and incorporate results from previous actions.
Accessing automation parameters
You can pass dynamic values from UI components and other automations into automations, making them reusable and flexible.
This is done using automation parameters with the params
namespace as follows:
{{params.
: Reference a value passed into the automation from a UI component or
other source. For example, parameterName
}}{{params.
would reference a parameter named ID
}}ID
.
Manipulating automation parameters
You can use JavaScript to manipulate automation parameters. See the following examples:
{{params.
: Concatenate values passed as parameters.firstName
}} {{params.lastName
}}{{params.
: Add two number parameters.numberParam1
+ params.numberParam2
}}{{params.
: Check if a parameter is not null or undefined, and has a non-zero length. If true, use the provided value; otherwise, set a default value.valueProvided
?.length > 0 ? params.valueProvided
: 'Default
'}}{{params.
: If therootCause
|| "No root cause provided
"}}params.
parameter is false (null, undefined, or an empty string), use the provided default value.rootCause
{{Math.min(params.
: Restrict the value of a parameter to a maximum value (in this case,numberOfProducts
,100
)}}100
).{{ DateTime.fromISO(params.
: If thestartDate
).plus({ days: 7 }).toISO() }}params.
parameter isstartDate
"2023-06-15T10:30:00.000Z"
, this expression will evaluate to"2023-06-22T10:30:00.000Z"
, which is the date one week after the start date.
Accessing automation results from a previous action
Automations allow application to run server-side logic and operations, such as querying databases, interacting with APIs, or
performing data transformations. The results
namespace provides access to the outputs and data returned by previous actions within the same automation. Note the following points about accessing automation results:
You can only access results of previous automation steps within the same automation.
If you have actions named
action1
andaction2
in that order,action1
cannot reference any results, andaction2
can only accessresults.
.action1
This also works in client-side actions. For example, if you have a button that triggers an automation using the
InvokeAutomation
action. You can then have a navigation step with aRun If
condition likeresults.
to navigate to a page with a PDF viewer if the automation indicates the file is a PDF.myInvokeAutomation1
.fileType === "pdf"
The following list contains the syntax for accessing automation results from a previous action using the results
namespace.
{{results.
: Retrieve the data array from an automation step namedstepName
.data}}stepName
.{{results.
: Retrieve the output of an automation step namedstepName
.output}}stepName
.
The way you access the results of an automation step depends on the type of action and the data it returns. Different actions may return different properties or data structures. Here are some common examples:
For a data action, you can access the returned data array using
results.
.stepName
.dataFor an API call action, you may access the response body using
results.
.stepName
.bodyFor an Amazon S3 action, you may access the file content using
results.
.stepName
.Body.transformToWebStream()
See the documentation for the specific action types you're using to understand the shape of the data they return and how to
access it within the results
namespace. The following list contains some examples
{{results.
: Assuming thegetDataStep
.data.filter(row => row.status === "pending").length}}getDataStep
is anInvoke Data Action
automation action that returns an array of data rows, this expression filters the data array to include only rows where the status field is equal topending
, and returns the length (count) of the filtered array. This can be useful for querying or processing data based on specific conditions.{{params.
: If theemail
.split("@")[0]}}params.
parameter contains an email address, this expression splits the string at the @ symbol and returns the part before the @ symbol, effectively extracting the username portion of the email address.email
{{new Date(params.
: This expression takes a Unix timestamp parameter (timestamp
* 1000)}}params.
) and converts it to a JavaScript Date object. It assumes that the timestamp is in seconds, so it multiplies it by 1000 to convert it to milliseconds, which is the format expected by thetimestamp
Date
constructor. This can be useful for working with date and time values in automations.{{results.
: For anstepName
.Body}}Amazon S3 GetObject
automation action namedstepName
, this expression retrieves the file content, which can be consumed by UI components like Image or PDF Viewer for displaying the retrieved file. Note that this expression would need to be configured in the Automation output of the automation to use in components.