

# Builder documentation
<a name="builder-documentation"></a>

The following topics contain information to help users in App Studio who are creating, editing, and publishing applications.

**Topics**
+ [Tutorials](tutorials.md)
+ [Building your App Studio app with generative AI](generative-ai.md)
+ [Creating, editing, and deleting applications](applications-create-edit-delete.md)
+ [Previewing, publishing, and sharing applications](applications-preview-publish-share.md)
+ [Pages and components: Build your app's user interface](pages-components-ux.md)
+ [Automations and actions: Define your app's business logic](automations.md)
+ [Entities and data actions: Configure your app's data model](data.md)
+ [Page and automation parameters](paramters.md)
+ [Using JavaScript to write expressions in App Studio](expressions.md)
+ [Data dependencies and timing considerations](data-dependencies-timing-considerations.md)
+ [Building an app with multiple users](builder-collaboration.md)
+ [Viewing or updating your app's content security settings](app-content-security-settings-csp.md)

# Tutorials
<a name="tutorials"></a>

**Topics**
+ [Build an AI text summarizer app with Amazon Bedrock](tutorial-conversational-bedrock.md)
+ [Interacting with Amazon Simple Storage Service with components and automations](automations-s3.md)
+ [Invoking Lambda functions in an App Studio app](tutorial-lambda.md)

# Build an AI text summarizer app with Amazon Bedrock
<a name="tutorial-conversational-bedrock"></a>

In this tutorial, you will build an application in App Studio that uses Amazon Bedrock to provide concise summaries of text input from end users. The application contains a simple user interface where users can input any text they want summarized. This could be meeting notes, article content, research findings, or any other textual information. After users enter the text, they can press a button to send the text to Amazon Bedrock, which will process it using the Claude 3 Sonnet model and return a summarized version.

**Contents**
+ [Prerequisites](#tutorial-conversational-bedrock-prerequisites)
+ [Step 1: Create and configure an IAM role and App Studio connector](#tutorial-conversational-bedrock-steps-create-role-connector)
+ [Step 2: Create an application](#tutorial-conversational-bedrock-steps-create-application)
+ [Step 3: Create and configure an automation](#tutorial-conversational-bedrock-steps-create-automation)
+ [Step 4: Create pages and components](#tutorial-conversational-bedrock-steps-user-interface)
  + [Rename the default page](#tutorial-conversational-bedrock-steps-user-interface-create-page)
  + [Add components to the page](#tutorial-conversational-bedrock-steps-user-interface-add-components)
  + [Configure the page components](#tutorial-conversational-bedrock-steps-user-interface-configure-components)
+ [Step 5: Publish the application to the **Testing** environment](#tutorial-conversational-bedrock-steps-publish)
+ [(Optional) Clean up](#tutorial-conversational-bedrock-steps-cleanup)

## Prerequisites
<a name="tutorial-conversational-bedrock-prerequisites"></a>

Before you get started, review and complete the following prerequisites:
+ Access to AWS App Studio. Note that you must have the Admin role to create a connector in this tutorial.
+ Optional: Review [AWS App Studio concepts](concepts.md) and the [Tutorial: Start building from an empty app](getting-started-tutorial-empty.md) to familiarize yourself with important App Studio concepts.

## Step 1: Create and configure an IAM role and App Studio connector
<a name="tutorial-conversational-bedrock-steps-create-role-connector"></a>

To provide App Studio access to Amazon Bedrock models, you must:

1. Enable the Amazon Bedrock models that you want to use in your app. For this tutorial, you will use **Claude 3 Sonnet**, so ensure you enable that model.

1. Create an IAM role with appropriate permissions to Amazon Bedrock.

1. Create an App Studio connector with the IAM role that will be used in your app.

Go to [Connect to Amazon Bedrock](connectors-bedrock.md) for detailed instructions, and return to this tutorial after you have followed the steps and created the connector.

## Step 2: Create an application
<a name="tutorial-conversational-bedrock-steps-create-application"></a>

Use the following procedure to create an empty app in App Studio that you will build into the text summarizer app.

1. Sign in to App Studio.

1. Navigate to the builder hub and choose **\$1 Create app**.

1. Choose **Start from scratch**.

1. In the **App name** field, provide a name for your app, such as **Text Summarizer**.

1. If you're asked to select data sources or a connector, choose **Skip** for the purposes of this tutorial.

1. Choose **Next** to proceed.

1. (Optional): Watch the video tutorial for a quick overview of building apps in App Studio.

1. Choose **Edit app**, which will bring you into the application studio.

## Step 3: Create and configure an automation
<a name="tutorial-conversational-bedrock-steps-create-automation"></a>

You define the logic and behavior of an App Studio app in *automations*. Automations consist of individual steps known as *actions*, *parameters* that are used to pass data to the action from other resources, and an *output* that can be used by other automations or components. In this step, you will create an automation that handles the interaction with Amazon Bedrock with the following:
+ Inputs: A parameter to pass the text input from the user to the automation.
+ Actions: One **GenAI Prompt** action that sends the text input to Amazon Bedrock and returns the output text summary.
+ Outputs: An automation output that consists of the processed summary from Amazon Bedrock, that can be used in your app.

**To create and configure an automation that sends a prompt to Amazon Bedrock and processes and returns a summary**

1. Choose the **Automations** tab at the top of the canvas.

1. Choose **\$1 Add automation**.

1. In the right-hand panel, choose **Properties**.

1. Update the automation name by choosing the pencil icon. Enter **InvokeBedrock** and press **Enter**.

1. Add a parameter to the automation that will be used to pass the text prompt input from the user into the automation to be used in the request to Amazon Bedrock by performing the following steps:

   1. In the canvas, in the parameters box, choose **\$1 Add**.

   1. In **Name**, enter **input**.

   1. In **Description**, enter any description, such as **Text to be sent to Amazon Bedrock**.

   1. In **Type**, select **String**.

   1. Choose **Add** to create the parameter.

1. Add a **GenAI Prompt** action by performing the following steps:

   1. In the right-hand panel, choose **Actions**.

   1. Choose **GenAI Prompt** to add an action.

1. Configure the action by performing the following steps:

   1. Choose the action from the canvas to open the right-hand **Properties** menu.

   1. Rename the action to **PromptBedrock** by choosing the pencil icon, entering the name, and pressing enter.

   1. In **Connector**, select the connector that was created in [Step 1: Create and configure an IAM role and App Studio connector](#tutorial-conversational-bedrock-steps-create-role-connector).

   1. In **Model**, choose the Amazon Bedrock model you want to use to process the prompt. In this tutorial, you will choose **Claude 3.5 Sonnet**.

   1. In **User prompt**, enter `{{params.input}}`. This represents the `input` parameter that you created earlier, and will contain the text input by your app users. 

   1. In **System prompt**, enter the system prompt instructions you want to send to Amazon Bedrock. For this tutorial, enter the following:

      ```
      You are a highly efficient text summarizer. Provide a concise summary of the prompted text, capturing the key points and main ideas.
      ```

   1. Choose **Request settings** to expand it, and update the following fields:
      + In **Temperature**, enter `0`. The tempearture determines the randomness or creativity of the output on a scale of 0 to 10. The higher the number, the more creative the response.
      + In **Max Tokens**, enter `4096` to limit the length of the response.

1. The output of this automation will be the summarized text, however, by default automations do not create outputs. Configure the automation to create an automation output by performing the following steps:

   1. In the left-hand navigation, choose the **InvokeBedrock** automation.

   1. In the right-hand **Properties** menu, in **Output**, choose **\$1 Add**.

   1. In **Output**, enter **\$1\$1results.PromptBedrock.text\$1\$1**. This expression returns the contents of the `processResults` action.

## Step 4: Create pages and components
<a name="tutorial-conversational-bedrock-steps-user-interface"></a>

In App Studio, each page represents a screen of your application's user interface (UI) that your users will interact with. Within these pages, you can add various components such as tables, forms, buttons, and more to create the desired layout and functionality. 

### Rename the default page
<a name="tutorial-conversational-bedrock-steps-user-interface-create-page"></a>

The text summarizer app in this tutorial will only contain one page. Newly created applications come with a default page, so you will rename that one instead of adding one.

**To rename the default page**

1. In the top bar navigation menu, choose **Pages**.

1. In the left-side panel, choose **Page1** and choose the **Properties** panel in the right-side panel.

1. Choose the pencil icon, enter **TextSummarizationTool**, and press **Enter**.

1. In **Navigation label** enter **TextSummarizationTool**.

### Add components to the page
<a name="tutorial-conversational-bedrock-steps-user-interface-add-components"></a>

For this tutorial, the text summarizer app has one page that contains the following components:
+ A **Text input** component that end users use to input a prompt to be summarized.
+ A **Button** component that is used to send the prompt to Amazon Bedrock.
+ A **Text area** component that displays the summary from Amazon Bedrock.

Add a **Text input** component to the page that users will use to input a text prompt to be summarized.

**To add a text input component**

1. In the right-hand **Components** panel, locate the **Text input** component and drag it onto the canvas.

1. Choose the text input in the canvas to select it.

1. In the right-side **Properties** panel, update the following settings:

   1. Choose the pencil icon to rename the text input to **inputPrompt**.

   1. In **Label**, enter **Prompt**.

   1. In **Placeholder**, enter **Enter text to be summarized**.

Now, add a **Button** component that users will choose to send the prompt to Amazon Bedrock.

**To add a button component**

1. In the right-hand **Components** panel, locate the **Button** component and drag it onto the canvas.

1. Choose the button in the canvas to select it.

1. In the right-side **Properties** panel, update the following settings:

   1. Choose the pencil icon to rename the button to **sendButton**.

   1. In **Button Label**, enter **Send**.

Now, add a **Text area** component that will display the summary returned by Amazon Bedrock.

**To add a text area component**

1. In the right-hand **Components** panel, locate the **Text area** component and drag it onto the canvas.

1. Choose the text area in the canvas to select it.

1. In the right-side **Properties** panel, update the following settings:

   1. Choose the pencil icon to rename the button to **textSummary**.

   1. In **Label**, enter **Summary**.

### Configure the page components
<a name="tutorial-conversational-bedrock-steps-user-interface-configure-components"></a>

Now that the app contains a page with components, the next step is to configure the components to carry out the appropriate behavior. To configure a component, such as a button, to take actions when it is interacted with, you must add a *trigger* to it. For the app in this tutorial, you will add two triggers to the `sendButton` button to do the following:
+ The first trigger sends the text in the `textPrompt` component to Amazon Bedrock to be analyzed.
+ The second trigger displays the returned summary from Amazon Bedrock in the `textSummary` component.

**To add a trigger that sends the prompt to Amazon Bedrock**

1. Choose the button in the canvas to select it.

1. In the right-side **Properties** panel, in the **Triggers** section, choose **\$1 Add**.

1. Choose **Invoke Automation**.

1. Choose the **InvokeAutomation1** trigger that was created to configure it.

1. In **Action Name**, enter **invokeBedrockAutomation**.

1. In **Invoke Automation**, select the **InvokeBedrock** automation that was created earlier.

1. In the parameters box, in the **input** parameter that was created earlier, enter **\$1\$1ui.inputPrompt.value\$1\$1**, which passes the content in the `inputPrompt` text input component.

1. Choose the left arrow at the top of the panel to return to the component properties menu.

Now, you've configured a trigger that invokes the automation to send a request to Amazon Bedrock when the button is clicked, the next step is to configure a second trigger that displays the results in the `textSummary` component.

**To add a trigger that displays the Amazon Bedrock results in the text area component**

1. In the right-side **Properties** panel of the button, in the **Triggers** section, choose **\$1 Add**.

1. Choose **Run component action**.

1. Choose the **Runcomponentaction1** trigger that was created to configure it.

1. In **Action Name**, enter **setTextSummary**.

1. In **Component**, select the **textSummary** component.

1. In **Action**, select **Set value**.

1. In **Set value to**, enter **\$1\$1results.invokeBedrockAutomation\$1\$1**.

## Step 5: Publish the application to the **Testing** environment
<a name="tutorial-conversational-bedrock-steps-publish"></a>

Typically, while you are building an app, it's good practice to preview it to see how it looks and do initial testing on its functionality. However, because applications don't interact with external services in the preview environment, you'll instead publish the app to the Testing environment to be able to test sending requests and receiving responses from Amazon Bedrock.

**To publish your app to the Testing environment**

1. In the top-right corner of the app builder, choose **Publish**.

1. Add a version description for the Testing environment.

1. Review and select the checkbox regarding the SLA. 

1. Choose **Start**. Publishing may take up to 15 minutes.

1. (Optional) When you're ready, you can give others access by choosing **Share** and following the prompts. For more information about sharing App Studio apps, see [Sharing published applications](application-share.md).

After testing your application, choose **Publish** again to promote the application to the Production environment. Note that apps in the Production environment aren't available to end users until they are shared. For more information about the different application environments, see [Application environments](applications-publish.md#application-environments). 

## (Optional) Clean up
<a name="tutorial-conversational-bedrock-steps-cleanup"></a>

You have now successfully completed the tutorial and built a text summarization app in App Studio with Amazon Bedrock. You can continue to use your app, or you can clean up the resources that were created in this tutorial. The following list contains a list of resources to be cleaned up:
+ The Amazon Bedrock connector created in App Studio. For more information, see [Viewing, editing, and deleting connectors](viewing-deleting-connectors.md).
+ The text summarizer app in App Studio. For more information, see [Deleting an application](applications-delete.md).
+ The IAM role created in the IAM console. For more information, see [Delete roles or instance profiles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_manage_delete.html) in the *AWS Identity and Access Management User Guide*.
+ If you requested model access to use Claude 3 Sonnet and want to revert access, see [Manage access to Amazon Bedrock foundation models](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html) in the *Amazon Bedrock User Guide*.

# Interacting with Amazon Simple Storage Service with components and automations
<a name="automations-s3"></a>

You can invoke various Amazon S3 operations from an App Studio app. For example, you could create a simple admin panel to manage your users and orders and display your media from Amazon S3. While you can invoke any Amazon S3 operation using the **Invoke AWS** action, there are four dedicated Amazon S3 actions that you can add to automations in your app to perform common operations on Amazon S3 buckets and objects. The four actions and their operations are as follows:
+ **Put Object**: Uses the `Amazon S3 PutObject` operation to add an object an Amazon S3 bucket.
+ **Get Object**: Uses the `Amazon S3 GetObject` operation to retrieve an object from an Amazon S3 bucket.
+ **List Objects**: Uses the `Amazon S3 ListObjects` operation to list objects in an Amazon S3 bucket.
+ **Delete Object**: Uses the `Amazon S3 DeleteObject` operation to delete an object from an Amazon S3 bucket.

In addition to the actions, there is an **S3 upload** component that you can add to pages in applications. Users can use this component to choose a file to upload, and the component calls `Amazon S3 PutObject` to upload the file to the configured bucket and folder. This tutorial will use this component in place of the standalone **Put Object** automation action. (The standalone action should be used in more complex scenarios that involve additional logic or actions to be taken before or after uploading.)

## Prerequisites
<a name="automations-s3-prerequisites"></a>

This guide assumes you have completed the following prerequisite:

1. Created and configured an Amazon S3 bucket, IAM role and policy, and Amazon S3 connector in order to successfully integrate Amazon S3 with App Studio. To create a connector, you must have the Administrator role. For more information, see [Connect to Amazon Simple Storage Service (Amazon S3)](connectors-s3.md).

## Create an empty application
<a name="automations-s3-create-app"></a>

Create an empty application to use throughout this guide by performing the following steps.

**To create an empty application**

1. In the navigation pane, choose **My applications**.

1. Choose **\$1 Create app**.

1. In the **Create app** dialog box, give your application a name, choose **Start from scratch**, and choose **Next**.

1. In the **Connect to existing data** dialog box, choose **Skip** to create the application.

1. Choose **Edit app** to be taken to the canvas of your new app, where you can use components, automations, and data to configure the look and function of your application.

## Create pages
<a name="automations-s3-create-pages"></a>

Create three pages in your application to gather or show information.

**To create pages**

1. If necessary, choose the **Pages** tab at the top of the canvas.

1. In the left-hand navigation, there is a single page that was created with your app. Choose **\$1 Add** twice to create two more pages. The navigation pane should show three total pages.

1. Update the name of the **Page1** page by performing the following steps:

   1. Choose the ellipses icon and choose **Page properties**.

   1. In the right-hand **Properties** menu, choose the pencil icon to edit the name.

   1. Enter **FileList** and press **Enter**.

1. Repeat the previous steps to update the second and third pages as follows:
   + Rename **Page2** to **UploadFile**.
   + Rename **Page3** to **FailUpload**.

Now, your app should have three pages named **FileList**, **UploadFile**, and **FailUpload**, which are shown in the left-hand **Pages** panel.

Next, you will create and configure the automations that interact with Amazon S3.

## Create and configure automations
<a name="automations-s3-automations"></a>

Create the automations of your application that interact with Amazon S3. Use the following procedures to create the following automations:
+ A **getFiles** automation that lists the objects in your Amazon S3 bucket, which will be used to fill a table component.
+ A **deleteFile** automation that deletes an object from your Amazon S3 bucket, which will be used to add a delete button to a table component.
+ A **viewFile** automation that gets an object from your Amazon S3 bucket and displays it, which will be used to show more details about a single object selected from a table component.

### Create a `getFiles` automation
<a name="automations-s3-get-files"></a>

Create an automation that will list the files in a specified Amazon S3 bucket.

1. Choose the **Automations** tab at the top of the canvas.

1. Choose **\$1 Add automation**.

1. In the right-hand panel, choose **Properties**.

1. Update the automation name by choosing the pencil icon. Enter **getFiles** and press **Enter**.

1. Add a **List objects** action by performing the following steps:

   1. In the right-hand panel, choose **Actions**.

   1. Choose **List objects** to add an action. The action should be named `ListObjects1`.

1. Configure the action by performing the following steps:

   1. Choose the action from the canvas to open the right-hand **Properties** menu.

   1. For **Connector**, choose the Amazon S3 connector that you created from the prerequisites.

   1. For **Configuration**, enter the following text, replacing *bucket\$1name* with the bucket you created in the prerequisites:

      ```
      {
        "Bucket": "bucket_name",
        "Prefix": ""
      }
      ```
**Note**  
You can use the `Prefix` field to limit the response to objects that begin with the specified string.

1. The output of this automation will be used to populate a table component with objects from your Amazon S3 bucket. However, by default, automations don't create outputs. Configure the automation to create an automation output by performing the following steps:

   1. In the left-hand navigation, choose the **getFiles** automation.

   1. On the right-hand **Properties** menu, in **Automation output**, choose **\$1 Add output**.

   1. For **Output**, enter **\$1\$1results.ListObjects1.Contents\$1\$1**. This expression returns the contents of the action, and can now be used to populate a table component.

### Create a `deleteFile` automation
<a name="automations-s3-delete-file"></a>

Create an automation that deletes an object from a specified Amazon S3 bucket.

1. In the left-hand **Automations** panel, choose **\$1 Add**.

1. Choose **\$1 Add automation**.

1. In the right-hand panel, choose **Properties**.

1. Update the automation name by choosing the pencil icon. Enter **deleteFile** and press **Enter**.

1. Add an automation parameter, used to pass data to an automation, by performing the following steps:

   1. On the right-hand **Properties** menu, in **Automation parameters**, choose **\$1 Add**.

   1. Choose the pencil icon to edit the automation parameter. Update the parameter name to **fileName** and press **Enter**.

1. Add a **Delete object** action by performing the following steps:

   1. In the right-hand panel, choose **Actions**.

   1. Choose **Delete object** to add an action. The action should be named `DeleteObject1`.

1. Configure the action by performing the following steps:

   1. Choose the action from the canvas to open the right-hand **Properties** menu.

   1. For **Connector**, choose the Amazon S3 connector that you created from the prerequisites.

   1. For **Configuration**, enter the following text, replacing *bucket\$1name* with the bucket you created in the prerequisites:

      ```
      {
        "Bucket": "bucket_name",
        "Key": params.fileName
      }
      ```

### Create a `viewFile` automation
<a name="automations-s3-view-file"></a>

Create an automation that retrieves a single object from a specified Amazon S3 bucket. Later, you will configure this automation with a file viewer component to display the object.

1. In the left-hand **Automations** panel, choose **\$1 Add**.

1. Choose **\$1 Add automation**.

1. In the right-hand panel, choose **Properties**.

1. Update the automation name by choosing the pencil icon. Enter **viewFile** and press **Enter**.

1. Add an automation parameter, used to pass data to an automation, by performing the following steps:

   1. On the right-hand **Properties** menu, in **Automation parameters**, choose **\$1 Add**.

   1. Choose the pencil icon to edit the automation parameter. Update the parameter name to **fileName** and press **Enter**.

1. Add a **Get object** action by performing the following steps:

   1. In the right-hand panel, choose **Actions**.

   1. Choose **Get object** to add an action. The action should be named `GetObject1`.

1. Configure the action by performing the following steps:

   1. Choose the action from the canvas to open the right-hand **Properties** menu.

   1. For **Connector**, choose the Amazon S3 connector that you created from the prerequisites.

   1. For **Configuration**, enter the following text, replacing *bucket\$1name* with the bucket you created in the prerequisites:

      ```
      {
        "Bucket": "bucket_name",
        "Key": params.fileName
      }
      ```

1. By default, automations don't create outputs. Configure the automation to create an automation output by performing the following steps:

   1. In the left-hand navigation, choose the **viewFile** automation.

   1. On the right-hand **Properties** menu, in **Automation output**, choose **\$1 Add output**.

   1. For **Output**, enter **\$1\$1results.GetObject1.Body.transformToWebStream()\$1\$1**. This expression returns the contents of the action.
**Note**  
You can read the response of `S3 GetObject` in the following ways:  
`transformToWebStream`: Returns a stream, which must be consumed to retrieve the data. If used as an automation output, the automation handles this, and the output can be used as a data source of an image or PDF viewer component. It can also be used as an input to another operation, such as `S3 PutObject`.
`transformToString`: Returns the raw data of the automation, and should be used in a JavaScript action if your files contain text content, such as JSON data. Must be awaited, for example: `await results.GetObject1.Body.transformToString();`
`transformToByteArray`: Returns an array of 8-bit unsigned integers. This response serves the purpose of a byte array, which allows storage and manipulation of binary data. Must be awaited, for example: `await results.GetObject1.Body.transformToByteArray();`

Next, you will add components to the pages you created earlier, and configure them with your automations so that users can use your app to view and delete files.

## Add and configure page components
<a name="automations-s3-components"></a>

Now that you have created the automations that define the business logic and functionality of your app, you will create components and connect them both.

### Add components to the **FileList** page
<a name="automations-s3-components-filelist-page"></a>

The **FileList** page that you created earlier will be used to display a list of files in the configured Amazon S3 bucket and more details about any file that is chosen from the list. To do that, you will do the following:

1. Create a table component to display the list of files. You will configure the table's rows to be filled with the output of the **getFiles** automation you previously created.

1. Create a PDF viewer component to display a single PDF. You will configure the component to view a file selected from the table, using the **viewFile** automation you previously created to fetch the file from your bucket.

**To add components to the **FileList** page**

1. Choose the **Pages** tab at the top of the canvas.

1. In the left-hand **Pages** panel, choose the **FileList** page.

1. On the right-hand **Components** page, find the **Table** component and drag it to the center of the canvas.

1. Choose the table component that you just added to the page.

1. On the right-hand **Properties** menu, choose the **Source** dropdown and select **Automation**.

1. Choose the **Automation** dropdown and select the **getFiles** automation. The table will use the output of the **getFiles** automation as its content.

1. Add a column to be filled with the name of the file.

   1. On the right-hand **Properties** menu, next to **Columns**, choose **\$1 Add**.

   1. Choose the arrow icon to the right of the **Column1** column that was just added.

   1. For **Column label**, rename the column to **Filename**.

   1. For **Value**, enter **\$1\$1currentRow.Key\$1\$1**.

   1. Choose the arrow icon at the top of the panel to return to the main **Properties** panel.

1. Add a table action to delete the file in a row.

   1. On the right-hand **Properties** menu, next to **Actions**, choose **\$1 Add**.

   1. In **Actions**, rename **Button** to **Delete**.

   1. Choose the arrow icon to the right of the **Delete** action that was just renamed.

   1. In **On click**, choose **\$1 Add action** and choose **Invoke automation**.

   1. Choose the action that was added to configure it.

   1. For **Action name**, enter **DeleteRecord**.

   1. In **Invoke automation**, select **deleteFile**.

   1. In the parameter text box, enter **\$1\$1currentRow.Key\$1\$1**.

   1. For **Value**, enter **\$1\$1currentRow.Key\$1\$1**.

1. In the right-hand panel, choose **Components** to view the components menu. There are two choices for showing files:
   + An **Image viewer** to view files with a `.png`, `.jpeg`, or `.jpg` extension.
   + A **PDF viewer** component to view PDF files.

   In this tutorial, you will add and configure the **PDF viewer** component.

1. Add the **PDF viewer** component.

   1. On the right-hand **Components** page, find the **PDF viewer** component and drag it to the canvas, below the table component.

   1. Choose the **PDF viewer** component that was just added.

   1. On the right-hand **Properties** menu, choose the **Source** dropdown and select **Automation**.

   1. Choose the **Automation** dropdown and select the **viewFile** automation. The table will use the output of the **viewFile** automation as its content.

   1. In the parameter text box, enter **\$1\$1ui.table1.selectedRow["Filename"]\$1\$1**.

   1. In the right-hand panel, there is also a **File name** field. The value of this field is used as the header for the PDF viewer component. Enter the same text as the previous step: **\$1\$1ui.table1.selectedRow["Filename"]\$1\$1**.

### Add components to the **UploadFile** page
<a name="automations-s3-components-uploadfile-page"></a>

The **UploadFile** page will contain a file selector that can be used to select and upload a file to the configured Amazon S3 bucket. You will add the **S3 upload** component to the page, which users can use to select and upload a file.

1. In the left-hand **Pages** panel, choose the **UploadFile** page.

1. On the right-hand **Components** page, find the **S3 upload** component and drag it to the center of the canvas.

1. Choose the S3 upload component that you just added to the page.

1. On the right-hand **Properties** menu, configure the component:

   1. In the **Connector** dropdown, select the Amazon S3 connector that was created in the prerequisites.

   1. For **Bucket**, enter the name of your Amazon S3 bucket.

   1. For **File name**, enter **\$1\$1ui.s3Upload1.files[0]?.nameWithExtension\$1\$1**.

   1. For **Max file size**, enter **5** in the text box, and ensure that **MB** is selected in the dropdown.

   1. In the **Triggers** section, add actions that run after successful or unsuccessful uploads by performing the following steps:

      To add an action that runs after successful uploads:

      1. In **On success**, choose **\$1 Add action** and select **Navigate**.

      1. Choose the action that was added to configure it.

      1. For **Navigation type**, choose **Page**.

      1. For **Navigate to**, choose **FileList**.

      1. Choose the arrow icon at the top of the panel to return to the main **Properties** panel.

      To add an action that runs after unsuccessful uploads:

      1. In **On failure**, choose **\$1 Add action** and select **Navigate**.

      1. Choose the action that was added to configure it.

      1. For **Navigation type**, choose **Page**.

      1. For **Navigate to**, choose **FailUpload**.

      1. Choose the arrow icon at the top of the panel to return to the main **Properties** panel.

### Add components to the **FailUpload** page
<a name="automations-s3-components-failupload-page"></a>

The **FailUpload** page is a simple page containing a text box that informs users that their upload failed.

1. In the left-hand **Pages** panel, choose the **FailUpload** page.

1. On the right-hand **Components** page, find the **Text** component and drag it to the center of the canvas.

1. Choose the text component that you just added to the page.

1. On the right-hand **Properties** menu, in **Value**, enter **Failed to upload, try again**.

## Update your app security settings
<a name="automations-s3-components-app-security-settings"></a>

Every application in App Studio has content security settings that you can use to restrict external media or resources, or which domains in Amazon S3 you can upload objects to. The default setting is to block all domains. To upload objects to Amazon S3 from your application, you must update the setting to allow the domains you want to upload objects to.

**To allow domains for uploading objects to Amazon S3**

1. Choose the **App settings** tab.

1. Choose the **Content Security Settings** tab.

1. For **Connect source**, choose **Allow all connections**.

1. Choose **Save**.

## Next steps: Preview and publish the application for testing
<a name="automations-s3-preview-publish-test"></a>

The application is now ready for testing. For more information about previewing and publishing applications, see [Previewing, publishing, and sharing applications](applications-preview-publish-share.md).

# Invoking Lambda functions in an App Studio app
<a name="tutorial-lambda"></a>

This tutorial shows you how to connect App Studio to Lambda and invoke Lambda functions from your apps.

## Prerequisites
<a name="tutorial-lambda-prerequisites"></a>

This guide assumes you have completed the following prerequisites:

1. Created an App Studio app. If you do not have one, you can create an empty app to use in the tutorial. For more information, see [Creating an application](applications-create.md).

**Note**  
While you don't need a Lambda function to follow this tutorial and learn how to configure it, it may be helpful to have one for ensuring you have correctly configured the app. This tutorial does not contain information about creating Lambda functions. for more information, see the [AWS Lambda Developer Guide](https://docs.aws.amazon.com/lambda/latest/dg/).

## Create a Lambda connector
<a name="tutorial-lambda-create-connector"></a>

To use Lambda functions in your App Studio app, you must use a connector to connect App Studio to Lambda to provide access to your functions. You must be an Administrator to create connectors in App Studio. For more information about creating Lambda connectors, including the steps to create one, see [Connect to AWS Lambda](connectors-lambda.md).

## Create and configure an automation
<a name="tutorial-lambda-automation"></a>

Automations are used to define the logic of your application and are made up of actions. To invoke a Lambda function in your app, you first add and configure an *Invoke Lambda* action to an automation. Use the following steps to create an automation and add the *Invoke Lambda* action to it.

1. While editing your app, choose the **Automations** tab.

1. Choose **\$1 Add automation**.

1. In the right-hand **Actions** menu, choose **Invoke Lambda** to add the step to your automation.

1. Choose the new Lambda step in the canvas to view and configure its properties.

1. In the right-hand **Properties** menu, configure the step by performing the following steps:

   1. In **Connector**, select the connector that was created to connect App Studio to your Lambda functions.

   1. In **Function name**, enter the name of your Lambda function.

   1. In **Function event**, enter the event to be passed to the Lambda function. Some common use case examples are provided in the following list:
      + Passing an automation parameter's value, such as a file name or other string: `varName: params.paramName`
      + Passing the result of a previous action: `varName: results.actionName1.data[0].fieldName`
      + If you add an *Invoke Lambda* action inside a *Loop* action, you can send fields from each iterated item similar to parameters: `varName: currentItem.fieldName`

   1. The **Mocked output** field can be used for providing mock output to test the app while previewing, where connectors are not active.

## Configure a UI element to run the automation
<a name="tutorial-lambda-create-pages"></a>

Now that you have an automation that is configured with an action to invoke your Lambda function, you can configure a UI element to run the automation. In this tutorial, you will create a button that runs the automation when clicked. 

**Tip**  
You can also run automations from other automations with the *Invoke automation* action.

**To run your automation from a button**

1. While editing your app, choose the **Pages** tab.

1. In the right-hand menu, choose the **Button** component to add a button to the page.

1. Choose the new button to configure it.

1. In the right-hand **Properties** menu, in **Triggers**, choose **\$1 Add** and choose **Invoke automation**.

1. Choose the new automation invoke trigger to configure it.

1. In **Invoke automation**, select the automation that invokes your Lambda function and configure any parameters that you want to send to the automation.

Now, any user that chooses this button in your app will cause the configured automation to run.

## Next steps: Preview and publish the application for testing
<a name="tutorial-lambda-preview-publish-test"></a>

Your application is now ready for testing. When previewing your app in the Development environment, connectors are not active, so you cannot test the automation while previewing as it uses a connector to connect to AWS Lambda. To test your app's functionality that depends on connectors, you must publish the app to the Testing environment. For more information about previewing and publishing applications, see [Previewing, publishing, and sharing applications](applications-preview-publish-share.md).

# Building your App Studio app with generative AI
<a name="generative-ai"></a>

AWS App Studio provides integrated generative AI capabilities to accelerate development and streamline common tasks. You can leverage generative AI to generate and edit apps, data models, sample data, and even get contextual help while building apps.

## Generating your app
<a name="generative-ai-generate-app"></a>

For an accelerated start, you can generate entire applications using natural language prompts powered by AI. This capability allows you to describe your desired app functionality, and AI will automatically build out the data models, user interfaces, workflows, and connectors. For more information about generating an app with AI, see [Creating an application](applications-create.md).

## Building or editing your app
<a name="generative-ai-build-app"></a>

While editing your application, you can use the chat to describe changes you want to make and your app is updated automatically. You can choose from the existing sample prompts or enter your own prompt. The chat can be used to add, edit, and remove supported components, and also create and configure automations and actions. Use the following procedure to use AI to edit or build your application.

**To edit your app with AI**

1. If necessary, edit your app to navigate to the application studio.

1. (Optional) Select the page or component that you want to edit with AI.

1. Choose **Build with AI** in the bottom left corner to open the chat.

1. Enter the changes that you want to make, or choose from the sample prompts.

1. Review the changes to be made. If you want the changes to be made, choose **Confirm**. Otherwise, enter another prompt.

1. Review summary of the changes.

## Generating your data models
<a name="generative-ai-data-model"></a>

You can automatically generate an entity with fields, data types, and data actions based on the provided entity name. For more information about creating entities, including creating entities using GenAi, see [Creating an entity in an App Studio app](data-entities-create.md).

You can also update an existing entity in the following ways:
+ Add more fields to an entity. For more information, see [Adding, editing, or deleting entity fields](data-entities-edit-fields.md).
+ Add data actions to an entity. For more information, see [Creating data actions](data-entities-edit-data-actions.md#data-entities-data-action-add).

## Generating sample data
<a name="generative-ai-generate-sample-data"></a>

You can generate sample data for your entities based on the entity's fields. This is useful to test your application before connecting external data sources, or testing your application in the Development environment, which doesn't communicate to external data sources. For more information, see [Adding or deleting sample data](data-entities-edit-sample-data.md).

Once you publish your app to Testing or Production, your live data sources and connectors are used in those environments.

## Configuring actions for AWS services
<a name="generative-ai-aws-actions-configuration"></a>

When integrating with AWS services like Amazon Simple Email Service, you can use AI to generate an example configuration with pre-populated fields based on the selected service. To try it out, In the **Properties** menu of an **Invoke AWS** automation action, expand the **Configuration** field by choosing the double-sided arrow. Then, choose **Generate sample configuration**.

## Mocking responses
<a name="generative-ai-mock-responses"></a>

You can generate mocked responses for AWS service actions. This is helpful for testing your application in the Development environment, which doesn't communicate to external data sources.

## Asking AI for help while building
<a name="generative-ai-ask-ai"></a>

Within the application studio, you'll find an **Ask AI for help** button on supported resources or properties. Use this to get contextual suggestions, documentation, and guidance related to the current view or selected component. Ask general questions about App Studio, app building best practices, or your specific application use case to receive tailored information and recommendations.

# Creating, editing, and deleting applications
<a name="applications-create-edit-delete"></a>

**Contents**
+ [Creating an application](applications-create.md)
+ [Importing applications](applications-import.md)
  + [Importable apps provided by App Studio](applications-import.md#app-catalog)
+ [Duplicating applications](applications-duplicate.md)
+ [Editing or building an application](applications-edit.md)
+ [Edit a previously published app version](applications-edit-previously-published-version.md)
+ [Renaming an application](applications-rename.md)
+ [Deleting an application](applications-delete.md)

# Creating an application
<a name="applications-create"></a>

Use the following procedure to create an application in App Studio.

**To create an application**

1. In the navigation pane, choose **My applications** in the **Build** section to navigate to a list of your applications.

1. Choose **\$1 Create app**.

1. In the **Create app** dialog box, give your application a name and choose one of the following app creation methods:
   + **Generate an app with AI**: Choose this option to describe your app with natural language, and have AI generate the app and its resources for you.
   + **Start from scratch**: Choose this option to start building from an empty app.

1. Choose **Next**.

1. If you chose **Generate an app with AI**:

   1. In the **Connect to existing data** dialog box, add any existing data sources to your app by select the **Connector** that provides App Studio access to the data sources, then select the **Tablse**, and choose **Next**. Adding data sources here helps AI generate an optimized app for you. You can skip this step and add data sources later by choosing **Skip**.

   1. After a brief delay (few minutes) delay, you are taken to the **Generate your app using AI** page, where you can describe the app you want to create.

   1. You can start describing your app in the chat, or you can choose and customize a provided sample prompt.

   1. After your prompt is analyzed, review the app requirements and overview. Use the chat to request any changes, or choose **Start over** to start from an empty prompt.

   1. When ready, choose **Generate app**.

   1. Once generated, preview your app in another tab by choosing **Preview app**. When you're ready to start editing, you can choose **Edit app**. Browse through the pages, automations, and data of your application to familiarize yourself with it. Review any errors or warnings in the bottom debug panel. To learn about generating an app using AI, see [Tutorial: Generate an app using AI](getting-started-tutorial-ai.md). For general information about how building in App Studio works, see [How AWS App Studio works](how-it-works.md).

1. If you chose **Start from scratch**:

   1. In the **Connect to existing data** dialog box, add any existing data sources to your app by select the **Connector** that provides App Studio access to the data sources, then select the **Tablse**, and choose **Next**. You can skip this step and add data sources later by choosing **Skip**.

   1. Once your app is created, choose **Edit app** to start editing your app. To learn about building from an empty app, see [Tutorial: Start building from an empty app](getting-started-tutorial-empty.md). For general information about how building in App Studio works, see [How AWS App Studio works](how-it-works.md).

# Importing applications
<a name="applications-import"></a>

You can import a copy of an exported application to your App Studio instance. You can import apps that have been exported from other App Studio instances, or apps from a catalog provided by App Studio. Importing an app from the App Studio app catalog can help you get started on an app with similar functionality, or help you learn about app building in App Studio by exploring the imported app.

When you import an app into your instance, a copy of the original app is created in your instance. After the new app is created, you are navigated to the Development environment of the app, where you can preview it and browse the app's functionality.

**Warning**  
When you import an app, you are importing all of the logic from the application, which could result in undesired or unexpected behavior. For example, there could be destructive queries that delete data from databases you connect to the application. We recommend thoroughly reviewing the application and its configuration, and testing it on non-production assets before connecting production data to it.

**To import an application**

1. In the navigation pane, choose **My applications** in the **Build** section to navigate to a list of your applications.

1. Choose the dropdown arrow next to **\$1 Create app**.

1. Choose **Import app**.

1. In the **Import app** dialog box, in **Import code**, enter the import code of the application that you want to import. For a list of apps provided by App Studio that can be imported, including app descriptions and import codes, see [Importable apps provided by App Studio](#app-catalog).

1. Choose **Import** to import the app and go to the Development environment of the imported app to view or edit it. For information building apps in App Studio, see [How AWS App Studio works](how-it-works.md)

## Importable apps provided by App Studio
<a name="app-catalog"></a>

App Studio provides apps that can be imported into your instance to help you learn about app building. To see how specific app functionality is implemented in App Studio, you can preview the applications and then browse their configuration in the Development environment.

The following table contains the list of applications, their import codes, and a brief description of the apps. Each app includes a `README` page that contains information about the app that you can view after you import it.


| App name | Description | Import code | 
| --- | --- | --- | 
|  **Swag Request Survey**  |  An internal swag request application designed for employees to order branded company merchandise. Employees can select items and specify sizes and submit their request through a simple form. This application handles all data through built-in storage, removing the need for external connections.  |  Swag Request Survey/ec4f5faf-e2f8-42ee-ab8d-6723d8ca21b2  | 
|  **Sprint Tracking**  |  A sprint management application that teams can use to organize and track software development work. Users can create sprints, add tasks, assign work, and monitor progress through dedicated sprint, track, and task views. This application handles all data through built-in storage, removing the need for external connections.  |  Sprint Tracking/8f31e160-771f-48d7-87b0-374e285e2fbc  | 
|  **Amazon Review Sentiment Tracker**  |  This application is a customer feedback analysis tool that generates sentiment scores from product reviews to help businesses understand customer satisfaction. The application includes sample data generation utilities for quick testing and requires an Amazon Bedrock connector for AI-powered insights, while maintaining all other data within the built-in storage system.  |  Amazon Review Sentiment Tracker/60f0dae4-f8e2-4c20-9583-fa456f5ebfab  | 
|  **Invoice and Receipt Processing**  |  This receipt processing application saves time and reduces errors by automating manual data entry and streamlining document approval workflows. The solution requires Amazon Textract, Amazon S3 and Amazon SES connectors. It uses an Amazon Textract to analyze and extract data from receipts stored in Amazon S3, then processes and emails the extracted information to approvers using Amazon SES.  |  Invoice and Receipt Processing/98bde3ae-e454-4b18-a1e6-6f23e8b2a4f1  | 
|  **Inspection and Inventory Audit**  |  An application for managing warehouse inspections and equipment tracking. Users can conduct pass/fail equipment assessments by room location, monitor inventory levels, and view inspection history. The application provides a centralized system for tracking both facility inspections and equipment status. This application handles all data through built-in storage, removing the need for external connections.  |  Inspection and Inventory Audit/cf570a06-1c5e-4dd7-9ea8-5c04723d687f  | 
|  **Product Adoption Tracker**  |  A comprehensive application for managing product development that centralizes customer feedback, feature requests and customer meeting notes. Teams can track customer interactions, organize requirements, and generate AI-powered reports for quarterly roadmap planning. The application includes sample data utilities and leverages Amazon Bedrock for AI insights and Amazon Aurora PostgreSQL for data management.  |  Product Adoption Tracker/9b3a4437-bb50-467f-ae9e-d108776b7ca1  | 
|  **Quick Embedding**  |  A demo application that enables users to view analytics while working with the underlying data. The app contains two methods for embedding Amazon Quick dashboards in App Studio: an API-based approach for registered and anonymous users (requiring Quick connector), and an iFrame integration for public dashboards.  |  Quicksight Embedding/0cdc15fc-ca8b-41b7-869e-ed13c9072bc8  | 
|  **Kitchen Sink**  |  A reference application showcasing advanced App Studio development tips and best practices. Includes working examples of state management, CSV data handling, browser API integration, and UI patterns that builders can study and implement in their own applications. None of the examples require external connections.  |  App Studio Kitchen Sink/1cfe6b2f-544c-4611-b82c-80eadc76a0c8  | 

# Duplicating applications
<a name="applications-duplicate"></a>

Application owners and co-owners can duplicate their apps to create an exact copy of the app. Duplicating apps is helpful if you want to preserve the current state for testing purposes, or use the duplicated app as a starter to create a new app.

**To duplicate an application**

1. In the navigation pane, choose **My applications** in the **Build** section. You will be taken to a page displaying a list of applications that you have access to.

1. Choose the dropdown in the **Actions** column of the application you want to duplicate.

1. Choose **Duplicate**. If the **Duplicate** optional is not avaiable, you're likely not a owner or co-owner of the application.

1. Optionally provide a name of the duplicated app. The default name is *Current\$1App\$1Name COPY*.

1. Choose **Duplicate**.

# Editing or building an application
<a name="applications-edit"></a>

Use the following procedure to edit an application in App Studio.

**To edit (build) an application**

1. In the navigation pane, choose **My applications** in the **Build** section. You will be taken to a page displaying a list of applications that you have access to.

1. In the **Actions** column of the application you want to edit, choose **Edit**. This will take you to the Development environment, where you can use components, automations, and data to configure the look and function of your application. For information about building applications, see [Getting started with AWS App Studio](getting-started.md).

# Edit a previously published app version
<a name="applications-edit-previously-published-version"></a>

Use the following procedure to edit a previously published version of your App Studio application. After you choose to edit the previously published version, you can edit the app in the Development environment, or publish it to Testing and then Production.

**Warning**  
The previously published version replaces the in-progress version of the app in the Development environment. Any unpublished changes to your app will be lost.

Editing a previously published version is useful in the case that you accidentally publish unwanted changes or changes that break the application for your users, and you want to further build or edit from the previous app version.

**Note**  
If you detect issues with a published app and need to immediately publish a previously working version, or you want to publish a previous version but preserve the latest updates to the app in the Development environment, you should rollback the app instead. For more information, see [Rolling back to a previously published version](application-rollback-version.md).

**To edit a previously published app version**

1. If necessary, navigate to the applicaiton studio of your application.

1. Choose the dropdown arrow next to the **Publish** button, and then choose **Publish Center**.

1. Choose **Version history** to see the list of previously published versions of the application.

1. Find the version you want to edit, and choose **Edit**.

1. Review the information, and choose **Revert**.

1. The version you chose to edit is now the current version in the Development environment. You can make changes to it, or publish it to the Testing environment as is by choosing **Publish**. Once published to Testing, you can publish again to the Production environment if desired.

# Renaming an application
<a name="applications-rename"></a>

Use the following procedure to rename an application in App Studio. You can rename an application from the list of applications, or from the Development environment while building the app.

**To rename an application**

1. In the navigation pane, choose **My applications** in the **Build** section. You will be taken to a page displaying a list of applications that you have access to.

1. You can rename an application from this list, or from the Development environment while editing.
   + To rename from this list:

     1. Choose the dropdown in the **Actions** column of the application you want to rename, then choose **Rename**.

     1. Give your application a new name, and choose **Rename**.
   + To rename from the Development environment:

     1. In the **Actions** column of the application you want to edit, choose **Edit**.

     1. In the Development environment, choose the application name and update it, then press Enter or navigate away from the text field to save your changes.

# Deleting an application
<a name="applications-delete"></a>

Use the following procedure to delete an application in App Studio.

**To delete an application**

1. In the navigation pane, choose **My applications** in the **Build** section. You will be taken to a page displaying a list of applications that you have access to.

1. Choose the dropdown in the **Actions** column of the application you want to delete.

1. Choose **Delete**.

1. In the **Delete application** dialog box, carefully review the information about deleting applications. If you want to delete the application, choose **Delete**.

# Previewing, publishing, and sharing applications
<a name="applications-preview-publish-share"></a>

**Topics**
+ [Previewing applications](applications-preview.md)
+ [Publishing applications](applications-publish.md)
+ [Sharing published applications](application-share.md)
+ [Rolling back to a previously published version](application-rollback-version.md)
+ [Exporting applications](applications-export.md)

# Previewing applications
<a name="applications-preview"></a>

You can preview applications in App Studio to see how they will appear to users and also test its functionality by using it and checking logs in a debug panel.

The application preview environment does not support displaying live data or the connection with external resources with connectors, such as data sources. To test functionality in the preview environment, you can use mocked output in automations and sample data in entities. To view your application with real-time data, you must publish your app. For more information, see [Publishing applications](applications-publish.md).

The preview or development environment does not update the application published in the other environments. If an application has not been published, users will not be able to access it until it is published and shared. If an application has already been published and shared, users will still access the version that has been published, and not the version used in a preview environment.

**To preview your application**

1. If necessary, navigate to the application studio of the application you want to preview:

   1. In the navigation pane, choose **My applications** in the **Build** section.

   1. Choose **Edit** for the application.

1. Choose **Preview** to open the preview environment for the application.

1. (Optional) Expand the debug panel by choosing its header near the bottom of the screen. You can filter the panel by type of message by choosing the type of message in the **Filter logs** section. You can clear the panel's logs by choosing **Clear console**.

1. While in the preview environment, you can test your application by navigating around its pages, using its components, and choosing its buttons to start automations that transfer data. Because the preview environment doesn't support live data or connections to external sources, you can view examples of the data being transferred in the debug panel.

# Publishing applications
<a name="applications-publish"></a>

When you've finished creating and configuring your application the next step is to publish it to test data transfers or share it with end users. To understand publishing applications in App Studio, it's important to understand the available environments. App Studio provides three separate environments, which are described in the following list:

1. **Development**: Where you build and preview your application. You do not need to publish to the Development environment, as the latest version of your application is hosted there automatically. No live data or third-party services or resources are available in this environment.

1. **Testing**: Where you can perform comprehensive testing of your application. In the Testing environment, you can connect to, send data to, and receive data from other services.

1. **Production**: The live operational environment for end-user consumption.

All of your app building takes place in the **Development** environment. Then, publish to the **Testing** environment to test data transfer between other services, and user acceptance testing (UAT) by providing an access URL to end users. Afterwards, publish your app to the **Production** environment to perform final tests before sharing it with users. For more information about the application environments, see [Application environments](#application-environments).

When you publish an application, it is not available for users until it is shared. This gives you the opportunity to use and test the application in the Testing and Production environments before users can access it. When you publish an application to Production that has previously been published and shared, the version that is available to users is updated.

## Publishing applications
<a name="application-publish-procedure"></a>

Use the following procedure to publish an App Studio application to the Testing or Production environment.

**To publish an application to Testing or Production environment**

1. In the navigation pane, choose **My applications** in the **Build** section. You will be taken to a page displaying a list of applications that you have access to.

1. Choose **Edit** for the application you want to publish.

1. Choose **Publish** in the top-right corner.

1. In the **Publish your updates** dialog box:

   1. Review the information about publishing an application.

   1. (Optional) In **Version description**, include a description of this version of the application.

   1. Choose the box to acknowledge the information about the environment.

   1. Choose **Start**. It can take up to 15 minutes for the application to be updated in the live environment.

1. For information about viewing applications in the Testing or Production environments, see [Viewing published applications](#application-viewing-published).
**Note**  
Using the application in the Testing or Production environment will result in live data transfer, such as creating records in tables of data sources that have been connected with connectors.

Published applications that have never been shared will not be available to users or other builders. To make an application available to users, you must share it after publishing. For more information, see [Sharing published applications](application-share.md).

## Viewing published applications
<a name="application-viewing-published"></a>

You can view applications published to the Testing and Production environments to test the application before sharing it with end users or other builders.

**To view published applications in the Testing or Production environment**

1. If necessary, navigate to the application studio of the application you want to preview:

   1. In the navigation pane, choose **My applications** in the **Build** section.

   1. Choose **Edit** for the application.

1. Choose the dropdown arrow next to **Publish** in the top-right corner and choose **Publish Center**.

1. From the publishing center, you can view the environments that your application is published to. If your application is published to the Testing or Production environments, you can view the app using the **URL** link for each environment.
**Note**  
Using the application in the Testing or Production environment will result in live data transfer, such as creating records in tables of data sources that have been connected with connectors.

## Application environments
<a name="application-environments"></a>

AWS App Studio provides application lifecycle management (ALM) capabilities with three separate environments - Development, Testing, and Production. This helps you more easily best practices such as maintaining separate environments, version control, sharing, and monitoring across the entire app lifecycle.

### Development environment
<a name="applications-development-environment"></a>

The **Development** environment is an isolated sandbox where you can build apps without connecting to any live data sources or services using the application studio and sample data. In the Development environment, you can preview your app to view and test the app without compromising production data.

Although your app doesn't connect to other services in the Development environment, you can configure different resources in your app to mimic live data connectors and automations.

There is a collapsible debug panel that includes errors and warnings at the bottom of the application studio in the Development environment to help you inspect and debug the app as you build. For more information about troubleshooting and debugging apps, see [Troubleshooting and debugging App Studio](troubleshooting-and-debugging.md).

### Testing environment
<a name="applications-testing-environment"></a>

Once your initial app development is complete, the next step is to publish to the **Testing** environment. While in the Testing environment, your app can connect to, send data to, and receive data from other services. Therefore, you can use this environment to perform comprehensive testing including user acceptance testing (UAT) by providing an access URL to end users.

**Note**  
Your initial publish to the Testing environment may take up to 15 minutes.

The version of your app published to the Testing environment will be removed after 3 hours of end-user inactivity. However, all versions persist and can be restored from the **Version History** tab.

Key features of the Testing environment are as follows:
+ Integration testing with live data sources and APIs
+ User acceptance testing (UAT) facilitated through controlled access
+ Environment for gathering feedback and addressing issues
+ Ability to inspect and debug both client-side and server-side activities using browser consoles and developer tools.

For more information about troubleshooting and debugging apps, see [Troubleshooting and debugging App Studio](troubleshooting-and-debugging.md).

### Production environment
<a name="applications-production-environment"></a>

After you have tested and fixed any issues, you can promote the version of your application from the Testing environment to the Production environment for live operational use. Although the Production environment is the live operational environment for end-user consumption, you can test the published version before sharing it with users.

Your published version in the Production environment will be removed after 14 days of end-user inactivity. However, all versions persist and can be restored from the **Version History** tab.

Key features of the Production environment are as follows:
+ Live operational environment for end-user consumption
+ Granular role-based access control
+ Version control and rollback capabilities
+ Ability to inspect and debug client-side activities only
+ Uses live connectors, data, automations, and APIs

## Versioning and release management
<a name="applications-versioning-release-management"></a>

App Studio provides version control and release management capabilities through its versioning system in the **Publish center**.

Key versioning capabilities:
+ Publishing to the Testing environment generates new version numbers (1.0, 2.0, 3.0...).
+ The version number does not change when promoting from the Testing to Production environment.
+ You can roll back to any previous version from **Version History**.
+ Applications published to the Testing environment are paused after 3 hours of inactivity. Versions are persisted and can be restored from **Version History**.
+ Applications published to the Production environment are removed after 14 days of inactivity. Versions are persisted and can be restored from **Version History**.

This versioning model allows for rapid iteration while maintaining traceability, rollback capabilities, and optimal performance across the app development and testing cycle.

## Maintenance and operations
<a name="applications-versioning-maintenance-operations"></a>

App Studio may need to automatically republish your application to address certain maintenance tasks, operational activities, and to incorporate new software libraries. No action is needed from you, the builder, but end users may need to log back into the application. In certain situations, we may need you to republish your application to incorporate new features and libraries which we cannot automatically add ourselves. You will need to resolve any errors and review warnings before republishing. 

# Sharing published applications
<a name="application-share"></a>

When you publish an application that has not been published yet, it is not available for users until it is shared. Once a published application has been shared, it will be available to users and will not need to be shared again if another version is published.

**Note**  
This section is about sharing published applications with end users or testers. For information about inviting other users to build an app, see [Building an app with multiple users](builder-collaboration.md).

**To share a published application**

1. Access the **Share** dialog box from either the application list, or the application studio of your app by using the following instructions:
   + To access the **Share** dialog box from the application list: In the navigation pane, choose **My applications** in the **Build** section. Choose the dropdown in the **Actions** column of the application you want to share and choose **Share**.
   + To access the **Share** dialog box from the application studio: From the application studio of your app, choose **Share** in the top header.

1. In the **Share** dialog box, choose the tab for the environment that you want to share. If you do not see the **Testing** or **Production** tabs, your app may not be published to the corresponding environment. For more information about publishing, see [Publishing applications](applications-publish.md).

1. In the appropriate tab, select groups from the dropdown menu to share the environment with them.

1. (Optional) Assign an app-level role to the group for testing or configuring conditional page visibiity. For more information, see [Configuring role-based visibility of pages](app-level-roles.md).

1. Choose **Share**.

1. (Optional) Copy and share the link with users. Only users that the application and environment have been shared with can access the application in the corresponding environment.

# Rolling back to a previously published version
<a name="application-rollback-version"></a>

Use the following procedure to roll back the Production environment of your App Studio app to a previously published version. Your application end users will be impacted and see the rolled back version of your app after it is deployed. When you roll back an application, it also rolls back the component code to the version from the previous publish time and affects the entire app deployment stack (user code, component configuration state). This means that any updates that App Studio made to component code, such as field or other config changes, will be rolled back to ensure the rolled-back application version operates as it did when it was originally published.

The in-progress version of your application in the Development environment is not affected when you roll back the published version.

Rolling back the published version of an application is helpful if you detect issues with a published app and need to immediately publish a previously working version, or you want to publish a previous version and preserve the latest updates to the app in the Development environment.

**Note**  
If you want to revert the Development environment of an app to a previously published version, you should revert the application. For more information, see [Edit a previously published app version](applications-edit-previously-published-version.md).

**To roll back the Production environment version to a previously published app version**

1. If necessary, navigate to the Development environment of your application by editing it. For more information, see [Editing or building an application](applications-edit.md).

1. Choose the version dropdown arrow at the top of the **Production** environment tile to see the available versions for rolling back. The dropdown contains versions published within the last 30 days. If this dropdown is disabled, it may be because an app publish is already in progress, and only one publish can happen at the same time.

1. Choose the version you want to roll back to.

1. Enter a reason for rolling back, and choose **Roll back**. The rollback publish will start and once completed, the Production environment of your application will be update to the chosen version.
**Note**  
You can also roll forward to a previously published app version after you've rolled back.

# Exporting applications
<a name="applications-export"></a>

You can export a snapshot of your application to share it with other App Studio instances. When you export an app, a snapshot is created from the Development environment of the app, and an import code is generated. The import code can then be used to import the application into other App Studio instances, where it can be viewed and built.

Exported apps can be imported into instances in any AWS Region supported by App Studio.

**To export an application**

1. In the navigation pane, choose **My applications** in the **Build** section to navigate to a list of your applications.

1. Choose the dropdown in the **Actions** column of the application you want to export.

1. Choose **Export**.

1. The procedure for generating and sharing an import code varies depending on whether or not an import code has already been created for the app.
   + If an import code hasn't been created:

     1. In **Application import permissions**, specify which instances can import the exported app. You can give import permissions to all instances, or add specific App Studio instances by entering their instance IDs. Separate multiple instance IDs with a comma.

        To find your instance ID, navigate to your instance's account settings by choosing **Account settings** in the App Studio console.

     1. Choose **Generate import code**.

     1. Copy and share the generated import code.
   + If an import code has already been created:

     1. To share the currently exported app, copy and share the existing import code. To create a new exported app with the latest changes to your app, choose **Generate new code**. You can also update the import permissions if needed.

# Pages and components: Build your app's user interface
<a name="pages-components-ux"></a>

**Topics**
+ [Managing pages](pages.md)
+ [Managing components](adding-editing-deleting-components.md)
+ [Configuring role-based visibility of pages](app-level-roles.md)
+ [Ordering and organizing pages in the app navigation](pages-order.md)
+ [Change colors in your app with app themes](app-theme.md)
+ [Components reference](components-reference.md)

# Managing pages
<a name="pages"></a>

Use the following procedures to create, edit, or delete pages from your AWS App Studio application.

**Pages** are containers for [components](concepts.md#concepts-component), which make up the UI of an application in App Studio. Each page represents a screen of your application's user interface (UI) that your users will interact with. Pages are created and edited in the **Pages** tab of the application studio.

# Creating a page
<a name="pages-create"></a>

Use the following procedure to create a page in an application in App Studio. For information about duplicating an existing page, see [Duplicating a page](pages-duplicate.md).

**To create a page**

1. If necessary, navigate to the Development environment of your application by editing it.

1. Navigate to the **Pages** tab.

1. In the left-side **Pages** menu, choose **\$1 Add**.

# Duplicating a page
<a name="pages-duplicate"></a>

Use the following procedure to duplicate a page in an application in App Studio.

**To duplicate a page**

1. If necessary, navigate to the Development environment of your application by editing it.

1. Navigate to the **Pages** tab.

1. In the left-side **Pages** menu, choose the ellipses menu next to the name of the page you want to duplicate and choose **Duplicate**. The duplicated page is added directly after the original page.

# Viewing and editing page properties
<a name="pages-edit"></a>

Use the following procedure to edit a page in an application in App Studio. You can edit properties such as the page's name, its parameters, and its layout.

**To view or edit page properties**

1. If necessary, navigate to the Development environment of your application by editing it.

1. Navigate to the **Pages** tab.

1. In the left-side **Pages** menu, choose the ellipses menu next to the name of the page you want to edit and choose **Page properties**. This opens the right-side **Properties** menu.

1. To edit the page name:
**Note**  
Valid page name characters: **A-Z**, **a-z**, **0-9**, **\$1**, **\$1**

   1. Choose the pencil icon next to the name near the top of the **Properties** menu.

   1. Enter the new name for your page and press Enter.

1. To create, edit, or delete page parameters:

   1. To create a page parameter, choose **\$1 Add new** in the **Page parameters** section.

   1. To edit a page parameter's **Key** or **Description** value, choose input field of the property you want to change and enter a new value. Your changes are saved as you edit.

   1. To delete a page parameter, choose the trash icon of the page parameter you want to delete.

1. To add, edit, or remove a page's logo or banner:

   1. To add a page logo or banner, enable the respective option in the **Style** section. Configure the image's source and optionally provide alt text.

   1. To edit a page logo or banner, update the fields in the **Style** section.

   1. To remove a page logo or banner, disable the respective option in the **Style** section.

1. To edit a page's layout:

   1. Update the fields in the **Layout** section.

# Deleting a page
<a name="pages-delete"></a>

Use the following procedure to delete a page from an application in App Studio.

**To delete a page**

1. If necessary, navigate to the Development environment of your application by editing it.

1. Navigate to the **Pages** tab.

1. In the left-side **Pages** menu, choose the ellipses menu next to the name of the page you want to delete and choose **Delete**.

# Managing components
<a name="adding-editing-deleting-components"></a>

Use the following procedures to add, edit, and delete components in or from pages in the App Studio application studio to craft the desired user interface for your application.

# Adding components to a page
<a name="adding-components"></a>

Use the following procedure to add a component to a page in App Studio. For information about duplicating an existing component, see [Duplicating components](duplicating-components.md).

1. If necessary, navigate to the Development environment of your application by editing it.

1. Navigate to the **Pages** tab.

1. The components panel is located in the right-side menu, which contains the available components.

1. Drag and drop the desired component from the panel onto the canvas. Alternatively, you can double-click on the component in the panel to automatically add it to the center of the current page.

1. Now that you've added a component, use the right-side **Properties** panel to adjust its settings, such as the data source, layout, and behavior. For detailed information about configuring each component type, see [Components reference](components-reference.md).

# Duplicating components
<a name="duplicating-components"></a>

Use the following procedure to duplicate a component in an App Studio app. Duplicated components contain any linked automations or entities from the original component.

1. If necessary, navigate to the Development environment of your application by editing it.

1. Navigate to the **Pages** tab.

1. There are two ways to duplicate a component:
   + In the left-side **Pages** menu, expand the page that contains the component you want to duplicate. Choose the ellipses menu next to the name of the component you want to duplicate and choose **Duplicate**.
   + Choose the component you want to duplicate, and choose the duplicate icon.

   The duplicated component is added directly after the original component.
**Tip**  
You can undo a component duplication, along with many other actions in the Development environment, by using the CTRL\$1Z or CMD\$1Z keyboard shortcuts.

# Viewing and editing component properties
<a name="editing-component-properties"></a>

1. If necessary, navigate to the Development environment of your application by editing it.

1. Navigate to the **Pages** tab.

1. In the left-side **Pages** menu, expand the page that contains the component and choose the component to be viewed or edited. Alternatively, you can choose the page and then choose the component from the canvas.

1. The right-side **Properties** panel displays the configurable settings for the selected component.

1. Explore the various properties and options available, and update them as necessary to configure the component's appearance and behavior. For example, you might want to change the data source, configure the layout, or enable additional functionality.

   For detailed information about configuring each component type, see [Components reference](components-reference.md).

# Deleting components
<a name="deleting-components"></a>

1. If necessary, navigate to the Development environment of your application by editing it.

1. Navigate to the **Pages** tab.

1. In the left-side **Pages** menu, choose the component to be deleted to select it.

1. In the right-side **Properties** menu, choose the trash icon.

1. In the confirmation dialog box, choose **Delete**.

# Configuring role-based visibility of pages
<a name="app-level-roles"></a>

You can create roles within an App Studio app and configure the visbility of pages based on those roles. For example, you can create roles based on user needs or access levels, such as administrator, manager, or user for apps that provide features such as project approvals or claims processing and make certain pages visible to specific roles. In this example, administrators may have full access, managers might have access to view reporting dashboards, and users may have access to tasks pages with input forms.

Use the following procedure to configure role-based visbility of pages in your App Studio app.

1. If necessary, navigate to the application studio of your application. From the left-side navigation menu, choose **My applications**, find your application and choose **Edit**.

1. Create app level roles in the application studio.

   1. Choose the **App settings** tab at the top of the application studio.

   1. Choose **\$1 Add Role**

   1. In **Role name**, provide a name to identify your role. We recommend using a name that is descriptive of the group's access level or duties, as you'll use the name to set up the page visibility.

   1. Optionally, in **Description**, add a description for the role.

   1. Repeat these steps to create as many roles as needed.

1. Configure the visiblity of your pages

   1. Choose the **Pages** tab at the top of the application studio.

   1. From the left-side **Pages** menu, choose the page for which you want to configure role-based visibility.

   1. In the right-side menu, choose the **Properties** tab.

   1. In **Visibility**, disable **Open to all end users**.

   1. Keep **Role** selected to choose from a list of the roles you created in the previous step. Choose **Custom** to write a JavaScript expression for more complex visibility configurations.

      1. With **Role** selected, check the boxes of the app roles for which the page will be visible.

      1. With **Custom** selected, enter a JavaScript expression that resolves to true or false. Use the following example to check if the current user has the role of *manager*: `{{currentUser.roles.includes('manager')}}`.

1. Now that your visibility is configured, you can test the page visiblity by previewing your app.

   1. Choose **Preview** to open a preview of your app.

   1. In the top right of the preview, choose the **Previewing as** menu and check the boxes of the roles you want to test. The visible pages should reflect the roles selected.

1. Now, assign groups to app roles for a published app. Group and role assignments must be configured separately for each environment. For more information about app environments, see [Application environments](applications-publish.md#application-environments).
**Note**  
Your app must be published to either the Testing or Production environments to assign App Studio groups to the roles you've created and configured. If necessary, publish your app to assign groups to the roles. For more information about publishing, see [Publishing applications](applications-publish.md).

   1. In the top right of the application studio, choose **Share**.

   1. Choose the tab for the environment of which you want to configure page visibility.

   1. Choose the **Search groups** input box and choose the group with which to share the app version. You can enter text to search for groups.

   1. In the dropdown menu, choose the roles to assign to the group. You can choose **No role** to share the app version and not assign a role to the group. Only pages that are visible to all users will be visible to groups with no role.

   1. Choose **Share**. Repeat these steps to add as many group as needed.

# Ordering and organizing pages in the app navigation
<a name="pages-order"></a>

This topic includes information about reordering and organizing pages in App Studio applications. There are two areas of the product where app pages are seen: in the left-hand **Pages** menu while editing the app in the application studio, and the left-hand navigation of a preview of published app.

## Ordering pages in the left-hand **Pages** menu while editing an app
<a name="pages-order-editing-app"></a>

While editing an app in the application studio, the pages are ordered by creation time in the left-hand **Pages** menu. You cannot reorder the pages in this menu.

## Ordering, showing, or hiding pages in the navigation of a preview or published app
<a name="pages-order-editing-app"></a>

You can edit the following settings of the left-hand navigation of a preview or published app:
+ The visibility of the entire navigation
+ The visibility of specific pages in the navigation
+ The order of the pages in the navigation

**To edit the left-hand navigation of a preview or published app**

1. If necessary, navigate to the application studio of your application to edit it.

1. In the left-side **Pages** menu, choose **Header & navigation**.

1. In the right-side **Header & navigation** menu, view or edit the following:

   1. To hide or show the navigation in the app, use the **App navigation** toggle.

   1. To hide pages from the navigation of the app, drag the pages to the **Unlinked pages** section.****

   1. To reorder pages in the navigation of the app, drag them to the desired order in the **Linked pages** section.

# Change colors in your app with app themes
<a name="app-theme"></a>

Use the following procedure to update the colors in your application by configuring an app theme.

1. If necessary, navigate to the application studio of your app to edit it.

1. In the application studio, navigate to the **Pages** tab.

1. In the left-hand navigation, choose **App theme** to open the right-hand app theme settings.

1. In **Base theme**, choose **Light mode** or **Dark mode**.

1. To add custom colors to your application, enable the **Customize** toggle and update the following settings:

   1. In **Primary color**, choose the color that is applied to certain components and your app's navigation. You can choose a color with the color picker, RGB, HSL, or HEX code.
**Note**  
App Studio will automatically ensure your colors are accessible. For example, if you choose a light color in light mode, it will be updated to be more accessible.

   1. In **Header color**, choose the color that is applied to your app's header. You can choose a color with the color picker, RGB, HSL, or HEX code.

   1. Choose **Default themes** to view and choose from predefined themes, or choose **Randomize** to generate a random primary and header color.

1. Choose **Save Changes** to update your app theme.

# Components reference
<a name="components-reference"></a>

This topic details each of App Studio's components, their properties, and includes configuration examples.

## Common component properties
<a name="common-properties"></a>

This section outlines the general properties and features that are shared across multiple components in the application studio. The specific implementation details and use cases for each property type may vary depending on the component, but the general concept of these properties remains consistent across App Studio.

### Name
<a name="common-properties-component-name"></a>

A default name is generated for each component; however, you can edit to change to a unique name to each component. You will use this name to reference the component and its data from other components or expressions within the same page. Limitation: Do not include spaces in the component name; it can only have have letters, numbers, underscores and dollar signs. Examples: `userNameInput`, `ordersTable`, `metricCard1`.

### Primary value, Secondary value, and Value
<a name="common-properties-component-values"></a>

Many components in the application studio provide fields for specifying values or expressions that determine the content or data displayed within the component. These fields are often labeled as `Primary value`, `Secondary value`, or simply `Value`, depending on the component type and purpose.

The `Primary value` field is typically used to define the main value, data point, or content that should be prominently displayed within the component.

The `Secondary value` field, when available, is used to display an additional or supporting value or information alongside the primary value.

The `Value` field allows you to specify the value or expression that should be displayed in the component.

These fields support both static text input and dynamic expressions. By using expressions, you can reference data from other components, data sources, or variables within your application, enabling dynamic and data-driven content display.

#### Syntax for expressions
<a name="common-properties-component-values-expression-syntax"></a>

The syntax for entering expressions in these fields follows a consistent pattern:

```
{{expression}}
```

Where *expression* is a valid expression that evaluates to the desired value or data you want to display.

##### Example: Static text
<a name="common-properties-component-values-static-text-examples"></a>
+ Primary value: you can enter a static number or value directly, such as `"123"` or `"$1,999.99"`.
+ Secondary value: you can enter a static text label, such as `"Goal"` or `"Projected Revenue"`.
+ Value: you can enter a static string, such as `"since last month"` or `"Total Quantity"`.

##### Examples: Expressions
<a name="common-properties-component-values-expression-examples"></a>
+ `Hello, {{currentUser.firstName}}`: Displays a greeting with the first name of the currently logged-in user.
+ `{{currentUser.role === 'Admin' ? 'Admin Dashboard' : 'User Dashboard'}}`: Conditionally displays a different dashboard title based on the user's role.
+ `{{ui.componentName.data?.[0]?.fieldName}}`: Retrieves the value of the `fieldName` field from the first item in the data of the component with the ID `componentName`.
+ `{{ui.componentName.value * 100}}`: Performs a calculation on the value of the component with the ID `componentName`.
+ `{{ui.componentName.value + ' items'}}`: Concatenates the value of the component with the ID `componentName` and the string `' items'`.
+ `{{ui.ordersTable.data?.[0]?.orderNumber}}`: Retrieves the order number from the first row of data in the `ordersTable` component.
+ `{{ui.salesMetrics.data?.[0]?.totalRevenue * 1.15}}`: Calculates the projected revenue by increasing the total revenue from the first row of data in the `salesMetrics` component by 15%.
+ `{{ui.customerProfile.data?.[0]?.firstName + ' ' + ui.customerProfile.data?.lastName}}`: Concatenates the first and last name from the data in the `customerProfile` component.
+ `{{new Date(ui.orderDetails.data?.orderDate).toLocaleDateString()}}`: Formats the order date from the `orderDetails` component to a more readable date string.
+ `{{ui.productList.data?.length}}`: Displays the total number of products in the data connected to the `productList` component.
+ `{{ui.discountPercentage.value * ui.orderTotal.value}}`: Calculates the discount amount based on the discount percentage and the order total.
+ `{{ui.cartItemCount.value + ' items in cart'}}`: Displays the number of items in the shopping cart, along with the label `items in cart`.

By using these expression fields, you can create dynamic and data-driven content within your application, allowing you to display information that is tailored to the user's context or the state of your application. This enables more personalized and interactive user experiences.

### Label
<a name="common-properties-label"></a>

The **Label** property allows you to specify a caption or title for the component. This label is typically displayed alongside or above the component, helping users understand its purpose.

You can use both static text and expressions to define the label.

#### Example: Static text
<a name="label-static-example"></a>

If you enter the text "First Name" in the Label field, the component will display "First Name" as its label.

#### Example: Expressions
<a name="label-expression-examples"></a>

##### Example: Retail store
<a name="label-expression-examples-retail-store-label"></a>

The following example personalizes the label for each user, making the interface feel more tailored to the individual:

```
{{currentUser.firstName}} {{currentUser.lastName}}'s Account
```

##### Example: SaaS project management
<a name="label-expression-examples-project-management-label"></a>

The following example pulls data from the selected project to provide context-specific labels, helping users stay oriented within the application:

```
Project {{ui.projectsTable.selectedRow.id}} - {{ui.projectsTable.selectedRow.name}}
```

##### Example: Healthcare clinic
<a name="label-expression-examples-healthcare-clinic-label"></a>

The following example references the current user's profile and the doctor's information, providing a more personalized experience for patients. 

```
Dr. {{ui.doctorProfileTable.data.firstName}}
       {{ui.doctorProfileTable.data.lastName}}
```

### Placeholder
<a name="common-properties-placeholder"></a>

The Placeholder property allows you to specify hint or guidance text that is displayed within the component when it is empty. This can help users understand the expected input format or provide additional context.

You can use both static text and expressions to define the placeholder.

#### Example: Static text
<a name="placeholder-static-example"></a>

If you enter the text `Enter your name` in the **Placeholder** field, the component will display `Enter your name` as the placeholder text.

#### Example: Expressions
<a name="placeholder-expression-examples"></a>

##### Example: Financial services
<a name="placeholder-expression-examples-financial-services-placeholder"></a>

 `Enter the amount you'd like to deposit into your {{ui.accountsTable.selectedRow.balance}} account` These examples pull data from the selected account to display relevant prompts, making the interface intuitive for banking customers. 

##### Example: E-commerce
<a name="placeholder-expression-examples-ecommerce-placeholder"></a>

 `Enter the coupon code for {{ui.cartTable.data.currency}} total` The placeholder here dynamically updates based on the user's cart contents, providing a seamless checkout experience. 

##### Example: Healthcare clinic
<a name="placeholder-expression-examples-healthcare-clinic-placeholder"></a>

 `Enter your {{ui.patientProfile.data.age}}-year-old patient's symptoms` By using an expression that references the patient's age, the application can create a more personalized and helpful placeholder. 

### Source
<a name="common-properties-source"></a>

The **Source** property allows you to select the data source for a component. Upon selection, you can choose from the following data source types: `entity`, `expression`, or `automation`.

#### Entity
<a name="common-properties-source-entity"></a>

Selecting **Entity** as the data source allows you to connect the component to an existing data entity or model in your application. This is useful when you have a well-defined data structure or schema that you want to leverage throughout your application.

When to use the entity data source:
+ When you have a data model or entity that contains the information you want to display in the component (e.g., a "Products" entity with fields like "Name", "Description", "Price").
+ When you need to dynamically fetch data from a database, API, or other external data source and present it in the component.
+ When you want to take advantage of the relationships and associations defined in your application's data model.

##### Selecting a query on an entity
<a name="common-properties-source-selecting-entity-query"></a>

Sometimes, you may want to connect a component to a specific query that retrieves data from an entity, rather than the entire entity. In the Entity data source, you have the option to choose from existing queries or create a new one.

By selecting a query, you can:
+ Filter the data displayed in the component based on specific criteria.
+ Pass parameters to the query to dynamically filter or sort the data.
+ Leverage complex joins, aggregations, or other data manipulation techniques defined in the query.

For example, if you have a `Customers` entity in your application with fields like `Name`, `Email`, and `PhoneNumber`. You can connect a table component to this entity and choose a pre-defined `ActiveCustomers` data action that filters the customers based on their status. This allows you to display only the active customers in the table, rather than the entire customer database.

##### Adding parameters to an entity data source
<a name="common-properties-source-adding-entity-parameters"></a>

When using an entity as the data source, you can also add parameters to the component. These parameters can be used to filter, sort, or transform the data displayed in the component.

For example, if you have a `Products` entity with fields like `Name`, `Description`, `Price`, and `Category`. You can add a parameter named `category` to a table component that displays the product list. When users select a category from a dropdown, the table will automatically update to show only the products belonging to the selected category, using the `{{params.category}}` expression in the data action.

#### Expression
<a name="common-properties-source-expression"></a>

Select **Expression** as the data source to enter custom expressions or calculations to generate the data for the component dynamically. This is useful when you need to perform transformations, combine data from multiple sources, or generate data based on specific business logic.

When to use the **Expression** data source:
+ When you need to calculate or derive data that is not directly available in your data model (e.g., calculating the total order value based on quantity and price).
+ When you want to combine data from multiple entities or data sources to create a composite view (e.g., displaying a customer's order history along with their contact information).
+ When you need to generate data based on specific rules or conditions (e.g., displaying a "Recommended Products" list based on the user's browsing history).

For example, if you have a *Metrics* component that needs to display the total revenue for the current month, you can use an expression like the following to calculate and display the monthly revenue:

```
{{ui.table1.orders.concat(ui.table1.orderDetails).filter(o => o.orderDate.getMonth() === new Date().getMonth()).reduce((a, b) => a + (b.quantity * b.unitPrice), 0)}}
```

##### Automation
<a name="common-properties-source-automation"></a>

Select **Automation** as the data source to connect the component to an existing automation or workflow in your application. This is useful when the data or functionality for the component is generated or updated as part of a specific process or workflow.

When to use the **Automation** data source:
+ When the data displayed in the component is the result of a specific automation or workflow (e.g., a "Pending Approvals" table that is updated as part of an approval process).
+ When you want to trigger actions or updates to the component based on events or conditions within an automation (e.g., updating a Metrics with the latest sales figures for a SKU).
+ When you need to integrate the component with other services or systems in your application through an automation (e.g., fetching data from a third-party API and displaying it in a table).

For example, if you have a stepflow component that guides users through a job application process. The stepflow component can be connected to an automation that handles the job application submission, background checks, and offer generation. As the automation progresses through these steps, the stepflow component can dynamically update to reflect the current status of the application.

By carefully selecting the appropriate data source for each component, you can ensure that your application's user interface is powered by the right data and logic, providing a seamless and engaging experience for your users.

### Visible if
<a name="visible-if"></a>

Use the **Visible if** property to show or hide components or elements based on specific conditions or data values. This is useful when you want to dynamically control the visibility of certain parts of your application's user interface.

The **Visible if** property uses the following syntax:

```
{{expression ? true : false}}
```

or

```
{{expression}}
```

Where *expression* is a boolean expression that evaluates to either `true` or `false`.

If the expression evaluates to `true`, the component will be visible. If the expression evaluates to `false`, the component will be hidden. The expression can reference values from other components, data sources, or variables within your application.

#### Visible if expression examples
<a name="visible-if-examples"></a>

##### Example: Showing or hiding a password input field based on an email input
<a name="visible-if-example-password-email"></a>

Imagine you have a login form with an email input field and a password input field. You want to show the password input field only if the user has entered an email address. You can use the following Visible if expression:

```
{{ui.emailInput.value !== ""}}
```

This expression checks if the value of the `emailInput` component is not an empty string. If the user has entered an email address, the expression evaluates to `true`, and the password input field will be visible. If the email field is empty, the expression evaluates to `false`, and the password input field will be hidden.

##### Example: Displaying additional form fields based on a dropdown selection
<a name="visible-if-example-form-fields-dropdown"></a>

Let's say you have a form where users can select a category from a dropdown list. Depending on the category selected, you want to show or hide additional form fields to gather more specific information.

For example, if the user selects the *Products* category, you can use the following expression to show an additional *Product Details* field:

```
{{ui.categoryDropdown.value === "Products"}}
```

If the user selects the *Services* or *Consulting* categories, you can use this expression to show a different set of additional fields:

```
{{ui.categoryDropdown.value === "Services" || ui.categoryDropdown.value === "Consulting"}}
```

##### Examples: Other
<a name="visible-if-example-other"></a>

To make the component visible if the `textInput1` component's value is not an empty string:

```
{{ui.textInput1.value === "" ? false : true}}
```

To make the component always visible:

```
{{true}}
```

To make the component visible if the `emailInput` component's value is not an empty string:

```
{{ui.emailInput.value !== ""}}
```

### Disabled if
<a name="disabled-if"></a>

The **Disabled if** feature allows you to conditionally enable or disable a component based on specific conditions or data values. This is achieved by using the **Disabled if** property, which accepts a boolean expression that determines whether the component should be enabled or disabled.

The **Disabled if** property uses the following syntax:

```
{{expression ? true : false}}
```

or

```
{{expression}}
```

#### Disabled if expression examples
<a name="disabled-if-examples"></a>

##### Example: Disabling a submit button based on form validation
<a name="disabled-if-example-disable-submit-button"></a>

If you have a form with multiple input fields, and you want to disable the submit button until all required fields are filled out correctly, you can use the following **Disabled If** expression:

```
{{ui.nameInput.value === "" || ui.emailInput.value === "" || ui.passwordInput.value === ""}}
```

This expression checks if any of the required input fields (`nameInput`, `emailInput`, `passwordInput`) are empty. If any of the fields are empty, the expression evaluates to `true`, and the submit button will be disabled. Once all the required fields are filled out, the expression evaluates to `false`, and the submit button will be enabled.

By using these types of conditional expressions in the **Visible if** and **Disabled ff** properties, you can create dynamic and responsive user interfaces that adapt to user input, providing a more streamlined and relevant experience for your application's users.

Where *expression* is a boolean expression that evaluates to either true or false.

Example:

```
{{ui.textInput1.value === "" ? true : false}}: The component will be Disabled if the textInput1 component's value is an empty string.
{{!ui.nameInput.isValid || !ui.emailInput.isValid || !ui.passwordInput.isValid}}: The component will be Disabled if any of the named input fields are invalid.
```

#### Container layouts
<a name="container-layouts"></a>

The layout properties determine how the content or elements within a component are arranged and positioned. Several layout options are available, each represented by an icon:
+ **Column Layout**: This layout arranges the content or elements vertically, in a single column.
+ **Two column layout**: This layout divides the component into two equal-width columns, allowing you to position content or elements side by side.
+ **Row layout**: This layout arranges the content or elements horizontally, in a single row.

##### Orientation
<a name="container-layouts-orientation"></a>
+ **Horizontal**: This layout arranges the content or elements horizontally, in a single row.
+ **Vertical**: This layout arranges the content or elements vertically, in a single column.
+ **Inline wrapped**: This layout arranges the content or elements horizontally, but wraps to the next line if the elements exceed the available width.

##### Alignment
<a name="container-layouts-alignment"></a>
+ **Left**: Aligns the content or elements to the left side of the component.
+ **Center**: Centers the content or elements horizontally within the component.
+ **Right**: Aligns the content or elements to the right side of the component.

##### Width
<a name="container-layouts-width"></a>

The **Width** property specifies the horizontal size of the component. You can enter a percentage value between 0% and 100%, representing the component's width relative to its parent container or the available space.

##### Height
<a name="container-layouts-height"></a>

The **Height** property specifies the vertical size of the component. The "auto" value adjusts the component's height automatically based on its content or the available space.

##### Space between
<a name="container-layouts-space-between"></a>

The **Space between** property determines the spacing or gap between the content or elements within the component. You can select a value from 0px (no spacing) to 64px, with increments of 4px (e.g., 4px, 8px, 12px, etc.).

##### Padding
<a name="container-layouts-padding"></a>

The **Padding** property controls the space between the content or elements and the edges of the component. You can select a value from 0px (no padding) to 64px, with increments of 4px (e.g., 4px, 8px, 12px, etc.).

##### Background
<a name="container-layouts-background"></a>

The **Background** enables or disables a background color or style for the component.

These layout properties provide flexibility in arranging and positioning the content within a component, as well as controlling the size, spacing, and visual appearance of the component itself.

## Data components
<a name="data-components"></a>

This section covers the various data components available in the application studio, including the **Table**, **Detail**, **Metric**, **Form**, and **Repeater** components. These components are used to display, gather, and manipulate data within your application.

### Table
<a name="table-component"></a>

The **Table** component displays data in a tabular format, with rows and columns. It is used to present structured data, such as lists of items or records from a database, in an organized and easy-to-read manner.

#### Table properties
<a name="table-component-properties"></a>

The **Table** component shares several common properties with other components, such as `Name`, `Source`, and `Actions`. For more information on these properties, see [Common component properties](#common-properties).

In addition to the common properties, the **Table** component has specific properties and configuration options, including `Columns`, `Search and export`, and `Expressions`.

##### Columns
<a name="table-component-properties-columns"></a>

In this section, you can define the columns to be displayed in the table. Each column can be configured with the following properties:
+ **Format**: The data type of the field, for example: text, number, date.
+ **Column label**: The header text for the column.
+ **Value**: The field from the data source that should be displayed in this column.

  This field allows you to specify the value or expression that should be displayed in the column cells. You can use expressions to reference data from the connected source or other components.

  Example: `{{currentRow.title}}` - This expression will display the value of the *title* field from the current row in the column cells.
+ **Enable sorting**: This toggle allows you to enable or disable sorting functionality for the specific column. When enabled, users can sort the table data based on the values in this column.

##### Search and export
<a name="table-component-properties-search-and-export"></a>

The **Table** component provides the following toggles to enable or disable search and export functionality:
+ **Show search** When enabled, this toggle adds a search input field to the table, allowing users to search and filter the displayed data.
+ **Show export** When enabled, this toggle adds an export option to the table, allowing users to download the table data in various formats, for example: CSV.

**Note**  
By default, the search functionality is limited to the data that has been loaded into the table. To use search exhaustively, you will need to load all pages of data.

##### Rows per page
<a name="table-component-properties-rows-per-page"></a>

You can specify the number of rows to be displayed per page in the table. Users can then navigate between pages to view the full dataset.

##### Pre-fetch limit
<a name="table-component-properties-pre-fetch-limit"></a>

Specify the maximum number of records to pre-fetch in each query request. The maximum is 3000.

##### Actions
<a name="table-component-properties-actions"></a>

In the **Actions** section, configure the following properties:
+ **Action location**: When **Pin to right** is enabled, any added actions will always show on the right of the table, regardless of user scrolling.
+ **Actions**: Add action buttons to the table. You can configure these buttons to do specified actions when clicked by a user, such as:
  + Run a component action
  + Navigate to a different page
  + Invoke a data action
  + Run custom JavaScript
  + Invoke an automation

##### Expressions
<a name="table-component-properties-expressions"></a>

The **Table** component provides several areas to use expressions and row-level action capabilities that allow you to customize and enhance the table's functionality and interactivity. They allow you to dynamically reference and display data within the table. By leveraging these expression fields, you can create dynamic columns, pass data to row-level actions, and reference table data from other components or expressions within your application.

##### Examples: Referencing row values
<a name="table-component-properties-examples-referencing-row-values"></a>

`{{currentRow.columnName}}` or `{{currentRow["Column Name"]}}` These expressions allow you to reference the value of a specific column for the current row being rendered. Replace *columnName* or *Column Name* with the actual name of the column you want to reference.

Examples:
+ `{{currentRow.productName}}` Displays the product name for the current row.
+ `{{currentRow["Supplier Name"]}}` Displays the supplier name for the current row, where the column header is *Supplier Name*.
+ `{{currentRow.orderDate}}` Displays the order date for the current row.

##### Examples: Referencing selected row
<a name="table-component-properties-examples-referencing-selected-row"></a>

`{{ui.table1.selectedRow["columnName"]}}` This expression allows you to reference the value of a specific column for the currently selected row in the table with the ID *table1*. Replace *table1* with the actual ID of your table component, and *columnName* with the name of the column you want to reference.

Examples:
+ `{{ui.ordersTable.selectedRow["totalAmount"]}}` Displays the total amount for the currently selected row in the table with the ID *ordersTable*.
+ `{{ui.customersTable.selectedRow["email"]}}` Displays the email address for the currently selected row in the table with the ID *customersTable*.
+ `{{ui.employeesTable.selectedRow["department"]}}` Displays the department for the currently selected row in the table with the ID *employeesTable*.

##### Examples: Creating custom columns
<a name="table-component-properties-examples-creating-custom-columns"></a>

You can add custom columns to a table based on data returned from the underlying data action, automation, or expression. You can use existing column values and JavaScript expressions to create new columns.

Examples:
+ `{{currentRow.quantity * currentRow.unitPrice}}` Creates a new column displaying the total price by multiplying the quantity and unit price columns.
+ `{{new Date(currentRow.orderDate).toLocaleDateString()}}` Creates a new column displaying the order date in a more readable format.
+ `{{currentRow.firstName + ' ' + currentRow.lastName + ' (' + currentRow.email + ')' }}` Creates a new column displaying the full name and email address for each row.

##### Examples: Customizing column display values:
<a name="table-component-properties-examples-customizing-column-display-values"></a>

You can customize the display value of a field within a table column by setting the `Value` field of the column mapping. This allows you to apply custom formatting or transformations to the displayed data.

Examples:
+ `{{ currentRow.rating >= 4 ? '⭐️'.repeat(currentRow.rating) : currentRow.rating }}` Displays star emojis based on the rating value for each row.
+ `{{ currentRow.category.toLowerCase().replace(/\b\w/g, c => c.toUpperCase()) }}` Displays the category value with each word capitalized for each row.
+ `{{ currentRow.status === 'Active' ? '🟢 Active' : '🔴 Inactive' }}`: Displays a colored circle emoji and text based on the status value for each row.

##### Row-level button actions
<a name="table-component-properties-examples-row-level-button-actions"></a>

`{{currentRow.columnName}}` or `{{currentRow["Column Name"]}}` You can use these expressions to pass the referenced row's context within a row-level action, such as navigating to another page with the selected row's data or triggering an automation with the row's data.

Examples:
+ If you have an edit button in the row action column, you can pass `{{currentRow.orderId}}` as a parameter to navigate to an order editing page with the selected order's ID.
+ If you have a delete button in the row action column, you can pass `{{currentRow.customerName}}` to an automation that sends a confirmation email to the customer before deleting their order.
+ If you have a view details button in the row action column, you can pass `{{currentRow.employeeId}}` to an automation that logs the employee who viewed the order details.

By leveraging these expression fields and row-level action capabilities, you can create highly customized and interactive tables that display and manipulate data based on your specific requirements. Additionally, you can connect row-level actions with other components or automations within your application, enabling seamless data flow and functionality.

### Detail
<a name="detail-component"></a>

The **Detail** component is designed to display detailed information about a specific record or item. It provides a dedicated space for presenting comprehensive data related to a single entity or row, making it ideal for showcasing in-depth details or facilitating data entry and editing tasks.

#### Detail properties
<a name="detail-component-properties"></a>

The **Detail** component shares several common properties with other components, such as `Name`, `Source`, and `Actions`. For more information on these properties, see [Common component properties](#common-properties).

The **Detail** component also has specific properties and configuration options, including `Fields`, `Layout`, and `Expressions`.

#### Layout
<a name="detail-component-properties-layout"></a>

The **Layout** section allows you to customize the arrangement and presentation of the fields within the **Detail** component. You can configure options such as:
+ **Number of columns**: Specify the number of columns to display the fields in.
+ **Field ordering**: Drag and drop fields to reorder their appearance.
+ **Spacing and alignment**: Adjust the spacing and alignment of fields within the component.

#### Expressions and examples
<a name="detail-component-properties-expressions"></a>

The **Detail** component provides various expression fields that allow you to reference and display data within the component dynamically. These expressions enable you to create customized and interactive **Detail** components that seamlessly connect with your application's data and logic.

##### Example: Referencing data
<a name="detail-component-properties-examples-referencing-data"></a>

`{{ui.details.data[0]?.["colName"]}}`: This expression allows you to reference the value of the column named "colName" for the first item (index 0) in the data array connected to the **Detail** component with the ID "details". Replace "colName" with the actual name of the column you want to reference. For example, the following expression will display the value of the "customerName" column for the first item in the data array connected to the "details" component:

```
{{ui.details.data[0]?.["customerName"]}}
```

**Note**  
This expression is useful when the **Detail** component is on the same page as the table being referenced, and you want to display data from the first row of the table in the **Detail** component.

##### Example: Conditional rendering
<a name="detail-component-properties-examples-conditional-rendering"></a>

`{{ui.table1.selectedRow["colName"]}}`: This expression returns true if the selected row in the table with the ID *table1* has data for the column named *colName*. It can be used to conditionally show or hide the **Detail** component based on whether the table's selected row is empty or not.

Example:

You can use this expression in the `Visible if` property of the **Detail** component to conditionally show or hide it based on the selected row in the table.

```
{{ui.table1.selectedRow["customerName"]}}
```

If this expression evaluates to true (the selected row in the *table1* component has a value for the *customerName* column), the **Detail** component will be visible. If the expression evaluates to false (i.e., the selected row is empty or does not have a value for "customerName"), the **Detail** component will be hidden.

##### Example: Conditional display
<a name="detail-component-properties-examples-conditional-display"></a>

`{{(ui.Component.value === "green" ? "🟢" : ui.Component.value === "yellow" ? "🟡" : ui.detail1.data?.[0]?.CustomerStatus)}}`: This expression conditionally displays an emoji based on the value of a component or data field.

Breakdown:
+ `ui.Component.value`: References the value of a component with the ID *Component*.
+ `=== "green"`: Checks if the component's value is equal to the string "green".
+ `? "🟢"`: If the condition is true, displays the green circle emoji.
+ `: ui.Component.value === "yellow" ? "🟡"`: If the first condition is false, checks if the component's value is equal to the string "yellow".
+ `? "🟡"`: If the second condition is true, displays the yellow square emoji.
+ `: ui.detail1.data?.[0]?.CustomerStatus`: If both conditions are false, it references the "CustomerStatus" value of the first item in the data array connected to the Detail component with the ID "detail1".

This expression can be used to display an emoji or a specific value based on the value of a component or data field within the **Detail** component.

### Metrics
<a name="metrics-component"></a>

The **Metrics** component is a visual element that displays key metrics or data points in a card-like format. It is designed to provide a concise and visually appealing way to present important information or performance indicators.

#### Metrics properties
<a name="metrics-properties"></a>

The **Metrics** component shares several common properties with other components, such as `Name`, `Source`, and `Actions`. For more information on these properties, see [Common component properties](#common-properties).

#### Trend
<a name="metrics-properties-trend"></a>

The Metrics's trend feature allows you to display a visual indicator of the performance or change over time for the metric being displayed.

##### Trend value
<a name="metrics-properties-trend-value"></a>

This field allows you to specify the value or expression that should be used to determine the trend direction and magnitude. Typically, this would be a value that represents the change or performance over a specific time period.

Example:

```
{{ui.salesMetrics.data?.[0]?.monthOverMonthRevenue}}
```

This expression retrieves the month-over-month revenue value from the first item in the data connected to the "salesMetrics" Metrics.

##### Positive trend
<a name="metrics-properties-positive-trend"></a>

This field allows you to enter an expression that defines the condition for a positive trend. The expression should evaluate to true or false.

Example:

```
{{ui.salesMetrics.data?.[0]?.monthOverMonthRevenue > 0}}
```

This expression checks if the month-over-month revenue value is greater than 0, indicating a positive trend.

##### Negative trend
<a name="metrics-properties-negative-trend"></a>

This field allows you to enter an expression that defines the condition for a negative trend. The expression should evaluate to true or false.

Example:

```
{{ui.salesMetrics.data?.[0]?.monthOverMonthRevenue < 0}}
```

This expression checks if the month-over-month revenue value is less than 0, indicating a negative trend.

##### Color bar
<a name="metrics-properties-color-bar"></a>

This toggle allows you to enable or disable the display of a colored bar to visually indicate the trend status.

##### Color Bar examples:
<a name="metrics-properties-color-bar-examples"></a>

##### Example: Sales metrics trend
<a name="metrics-properties-color-bar-examples-sales-metrics-trend"></a>
+ **Trend value**: `{{ui.salesMetrics.data?.[0]?.monthOverMonthRevenue}}`
+ **Positive trend**: `{{ui.salesMetrics.data?.[0]?.monthOverMonthRevenue > 0}}`
+ **Negative trend**: `{{ui.salesMetrics.data?.[0]?.monthOverMonthRevenue < 0}}`
+ **Color bar**: Enabled

##### Example: inventory metrics trend
<a name="metrics-properties-color-bar-examples-inventory-metrics-trend"></a>
+ **Trend value**: `{{ui.inventoryMetrics.data?.[0]?.currentInventory - ui.inventoryMetrics.data?.[1]?.currentInventory}}`
+ **Positive trend**: `{{ui.inventoryMetrics.data?.[0]?.currentInventory > ui.inventoryMetrics.data?.[1]?.currentInventory}}`
+ **Negative trend**: `{{ui.inventoryMetrics.data?.[0]?.currentInventory < ui.inventoryMetrics.data?.[1]?.currentInventory}}`
+ **Color Bbar**: Enabled

##### Example: Customer satisfaction trend
<a name="metrics-properties-color-bar-examples-customer-satisfaction-trend"></a>
+ **Trend value**: `{{ui.customerSatisfactionMetrics.data?.[0]?.npsScore}}`
+ **Positive trend**: `{{ui.customerSatisfactionMetrics.data?.[0]?.npsScore >= 8}}`
+ **Negative trend**: `{{ui.customerSatisfactionMetrics.data?.[0]?.npsScore < 7}}`
+ **Color bar**: Enabled

By configuring these trend-related properties, you can create **Metrics** components that provide a visual representation of the performance or change over time for the metric being displayed.

By leveraging these expressions, you can create highly customized and interactive metrics components that reference and display data dynamically, allowing you to showcase key metrics, performance indicators, and data-driven visualizations within your application.

#### Metrics expression examples
<a name="metrics-expression-examples"></a>

In the properties panel, you can enter expressions to display the title, primary value, secondary value, and value caption to dynamically display a value.

##### Example: Referencing primary value
<a name="metrics-expression-examples-referencing-primary-value"></a>

`{{ui.metric1.primaryValue}}`: This expression allows you to reference the primary value of the **Metrics** component with the ID *metric1* from other components or expressions within the same page.

Example: `{{ui.salesMetrics.primaryValue}}` will display the primary value of the *salesMetrics* **Metrics** component.

##### Example: Referencing secondary value
<a name="metrics-expression-examples-referencing-secondary-value"></a>

`{{ui.metric1.secondaryValue}}`: This expression allows you to reference the secondary value of the **Metrics** component with the ID *metric1* from other components or expressions within the same page.

Example: `{{ui.revenueMetrics.secondaryValue}}` will display the secondary value of the *revenueMetrics* **Metrics** component.

##### Example: Referencing data
<a name="metrics-expression-examples-referencing-data"></a>

`{{ui.metric1.data}}`: This expression allows you to reference the data of the **Metrics **component with the ID *metric1* from other components or expressions within the same page.

Example: `{{ui.kpiMetrics.data}}` will reference the data connected to the *kpiMetrics* **Metrics** component.

##### Example: Displaying specific data values:
<a name="metrics-expression-examples-displaying-specific-data-values"></a>

`{{ui.metric1.data?.[0]?.id}}`: This expression is an example of how to display a specific piece of information from the data connected to the **Metrics** component with the ID *metric1*. It is useful when you want to display a specific property of the first item in the data.

Breakdown:
+ `ui.metric1`: References the **Metrics** component with the ID *metric1*.
+ `data`: Refers to the information or data set connected to that component.
+ `?.[0]`: Means the first item or entry in that data set.
+ `?.id`: Displays the *id* value or identifier of that first item or entry.

Example: `{{ui.orderMetrics.data?.[0]?.orderId}}` will display the *orderId* value of the first item in the data connected to the *orderMetrics* **Metrics** component.

##### Example: Displaying data length
<a name="metrics-expression-examples-displaying-data-length"></a>

`{{ui.metric1.data?.length}}`: This expression demonstrates how to display the length (number of items) in the data connected to the **Metrics** component with the ID *metric1*. It is useful when you want to display the number of items in the data.

Breakdown:
+ `ui.metric1.data`: References the data set connected to the component.
+ `?.length`: Accesses the total count or number of items or entries in that data set.

Example: `{{ui.productMetrics.data?.length}}` will display the number of items in the data connected to the *productMetrics* **Metrics** component.

### Repeater
<a name="repeater-component"></a>

The **Repeater** component is a dynamic component that allows you to generate and display a collection of elements based on a provided data source. It is designed to facilitate the creation of lists, grids, or repeating patterns within your application's user interface. A few example use cases include:
+ Displaying a card for each user in an account
+ Showing a list of products that include images and a button to add it to the cart
+ Showing a list of files the user can access

The **Repeater** component differentiates itself from the **Table** component with rich content. A **Table** component has a strict row and column format. The **Repeater** can display your data more flexibly.

#### Repeater properties
<a name="repeater-component-properties"></a>

The **Repeater** component shares several common properties with other components, such as `Name`, `Source`, and `Actions`. For more information on these properties, see [Common component properties](#common-properties).

In addition to the common properties, the **Repeater** component has the following additional properties and configuration options.

#### Item template
<a name="repeater-component-properties-item-template"></a>

The **Item template** is a container where you can define the structure and components that will be repeated for each item in the data source. You can drag and drop other components into this container, such as **Text**, **Image**, **Button**, or any other component you need to represent each item.

Within the **Item template**, you can reference properties or values from the current item using expressions in the format `{{currentItem.propertyName}}`.

For example, if your data source contains an `itemName` property, you can use `{{currentItem.itemName}}` to display the item name(s) of the current item.

#### Layout
<a name="repeater-component-properties-layout"></a>

The **Layout** section allows you to configure the arrangement of the repeated elements within the Repeater Component.

##### Orientation
<a name="repeater-component-properties-orientation"></a>
+ **List**: Arranges the repeated elements vertically in a single column.
+ **Grid**: Arranges the repeated elements in a grid layout with multiple columns.

##### Rows per page
<a name="repeater-component-properties-rows-per-page"></a>

Specify the number of rows to display per page in the list layout. Pagination is provided for items that overflow the specified number of rows.

##### Columns and Rows per Page (Grid)
<a name="columns-and-rows-per-page-grid"></a>
+ **Columns**: Specify the number of columns in the grid layout.
+ **Rows per Page**: Specify the number of rows to display per page in the grid layout. Pagination is provided for items that overflow the specified grid dimensions.

#### Expressions and examples
<a name="repeater-component-properties-expressions"></a>

The **Repeater** component provides various expression fields that allow you to reference and display data within the component dynamically. These expressions enable you to create customized and interactive **Repeater** components that seamlessly connect with your application's data and logic.

##### Example: Referencing items
<a name="repeater-component-properties-expressions-examples-referencing-items"></a>
+ `{{currentItem.propertyName}}`: Reference properties or values from the current item within the **Item Template**.
+ `{{ui.repeaterID[index]}}`: Reference a specific item in the Repeater Component by its index.

##### Example: Rendering a list of products
<a name="repeater-component-properties-expressions-examples-rendering-product-list"></a>
+ **Source**: Select the *Products* entity as the data source.
+ **Item Template**: Add a **Container** component with a **Text** component inside to display the product name (`{{currentItem.productName}}`) and an **Image** component to display the product image (`{{currentItem.productImageUrl}}`).
+ **Layout**: Set the `Orientation` to `List` and adjust the `Rows per Page` as desired.

##### Example: Generating a grid of user avatars
<a name="repeater-component-properties-expressions-examples-generating-user-avatar-grid"></a>
+ **Source**: Use an expression to generate an array of user data (e.g., `[{name: 'John', avatarUrl: '...'}, {...}, {...}]`).
+ **Item Template**: Add an **Image** component and set its `Source` property to `{{currentItem.avatarUrl}}`.
+ **Layout**: Set the `Orientation` to `Grid`, specify the number of `Columns` and `Rows per Page`, and adjust the `Space Between` and `Padding` as needed.

By using the `Repeater` component, you can create dynamic and data-driven user interfaces, streamlining the process of rendering collections of elements and reducing the need for manual repetition or hard-coding.

### Form
<a name="form-component"></a>

The Form component is designed to capture user input and facilitate data entry tasks within your application. It provides a structured layout for displaying input fields, dropdowns, checkboxes, and other form controls, allowing users to input or modify data seamlessly. You can nest other components inside of a form component, such as a table.

#### Form properties
<a name="form-component-properties"></a>

The **Form** component shares several common properties with other components, such as `Name`, `Source`, and `Actions`. For more information on these properties, see [Common component properties](#common-properties).

#### Generate Form
<a name="form-component-properties-generate-form"></a>

The **Generate Form** feature makes it easy to quickly create form fields by automatically populating them based on a selected data source. This can save time and effort when building forms that need to display a large number of fields.

**To use the **Generate Form** feature:**

1. In the **Form** component's properties, locate the **Generate Form** section.

1. Select the data source you want to use to generate the form fields. This can be an entity, workflow, or any other data source available in your application.

1. The form fields will be automatically generated based on the selected data source, including the field labels, types, and data mappings.

1. Review the generated fields and make any necessary customizations, such as adding validation rules or changing the field order.

1. Once you're satisfied with the form configuration, choose **Submit** to apply the generated fields to your **Form** component.

The **Generate Form** feature is particularly useful when you have a well-defined data model or set of entities in your application that you need to capture user input for. By automatically generating the form fields, you can save time and ensure consistency across your application's forms.

After using the **Generate Form** feature, you can further customize the layout, actions, and expressions for the **Form** component to fit your specific requirements.

#### Expressions and examples
<a name="form-component-properties-expressions"></a>

Like other components, you can use expressions to reference and display data within the **Form** component. For example:
+ `{{ui.userForm.data.email}}`: References the value of the `email` field from the data source connected to the **Form** component with the ID `userForm`.

**Note**  
See [Common component properties](#common-properties) for more expression examples of the common properties.

By configuring these properties and leveraging expressions, you can create customized and interactive Form components that seamlessly integrate with your application's data sources and logic. These components can be used to capture user input, display pre-populated data, and trigger actions based on the form submissions or user interactions.

### Stepflow
<a name="stepflow-component"></a>

The **Stepflow** component is designed to guide users through multi-step processes or workflows within your application. It provides a structured and intuitive interface for presenting a sequence of steps, each with its own set of inputs, validations, and actions.

The Stepflow component shares several common properties with other components, such as `Name`, `Source`, and `Actions`. For more information on these properties, see [Common component properties](#common-properties).

The **Stepflow** component has additional properties and configuration options, such as `Step Navigation`, `Validation`, and `Expressions`.

## AI components
<a name="ai-components"></a>

### Gen AI
<a name="genai-component"></a>

The **Gen AI** component is a grouping container that is used to group components and their accompanying logic to easily edit them with AI using chat within the application studio. When you use the chat to create components, they will be grouped into a **Gen AI** container. For information about editing or using this component, see [Building or editing your app](generative-ai.md#generative-ai-build-app).

## Text & number components
<a name="text-and-number-components"></a>

### Text input
<a name="text-input-component"></a>

The **Text input** component allows users to enter and submit text data within your application. It provides a simple and intuitive way to capture user input, such as names, addresses, or any other textual information.
+ `{{ui.inputTextID.value}}`: Returns the provided value in the input field.
+ `{{ui.inputTextID.isValid}}`: Returns the validity of the provided value in the input field.

### Text
<a name="text-component"></a>

The **Text** component is used to display textual information within your application. It can be used to show static text, dynamic values, or content generated from expressions.

### Text area
<a name="text-area-component"></a>

The **Text area** component is designed to capture multi-line text input from users. It provides a larger input field area for users to enter longer text entries, such as descriptions, notes, or comments.
+ `{{ui.textAreaID.value}}`: Returns the provided value in the text area.
+ `{{ui.textAreaID.isValid}}`: Returns the validity of the provided value in the text area.

### Email
<a name="email-component"></a>

The **Email** component is a specialized input field designed to capture email addresses from users. It can enforce specific validation rules to ensure the entered value adheres to the correct email format.
+ `{{ui.emailID.value}}`: Returns the provided value in the email input field.
+ `{{ui.emailID.isValid}}`: Returns the validity of the provided value in the email input field.

### Password
<a name="password-component"></a>

The **Password** component is an input field specifically designed for users to enter sensitive information, such as passwords or PIN codes. It masks the entered characters to maintain privacy and security.
+ `{{ui.passwordID.value}}`: Returns the provided value in the password input field.
+ `{{ui.passwordID.isValid}}`: Returns the validity of the provided value in the password input field.

### Search
<a name="search-component"></a>

The **Search** component provides users with a dedicated input field for performing search queries or entering search terms within the populated data within the application.
+ `{{ui.searchID.value}}`: Returns the provided value in the search field.

### Phone
<a name="phone-component"></a>

The **Phone** component is an input field tailored for capturing phone numbers or other contact information from users. It can include specific validation rules and formatting options to ensure the entered value adheres to the correct phone number format.
+ `{{ui.phoneID.value}}`: Returns the provided value in the phone input field.
+ `{{ui.phoneID.isValid}}`: Returns the validity of the provided value in the phone input field.

### Number
<a name="number-component"></a>

The **Number** component is an input field designed specifically for users to enter numerical values. It can enforce validation rules to ensure the entered value is a valid number within a specified range or format.
+ `{{ui.numberID.value}}`: Returns the provided value in the number input field.
+ `{{ui.numberID.isValid}}`: Returns the validity of the provided value in the number input field.

### Currency
<a name="currency-component"></a>

The **Currency** component is a specialized input field for capturing monetary values or amounts. It can include formatting options to display currency symbols, decimal separators, and enforce validation rules specific to currency inputs.
+ `{{ui.currencyID.value}}`: Returns the provided value in the currency input field.
+ `{{ui.currencyID.isValid}}`: Returns the validity of the provided value in the currency input field.

### Detail pair
<a name="detail-pair-component"></a>

The **Detail pair** component is used to display key-value pairs or pairs of related information in a structured and readable format. It is commonly used to present details or metadata associated with a specific item or entity.

## Selection components
<a name="selection-components"></a>

### Switch
<a name="switch-component"></a>

The **Switch** component is a user interface control that allows users to toggle between two states or options, such as on/off, true/false, or enabled/disabled. It provides a visual representation of the current state and allows users to change it with a single click or tap.

### Switch group
<a name="switch-group-component"></a>

The **Switch group** component is a collection of individual switch controls that allow users to select one or more options from a predefined set. It provides a visual representation of the selected and unselected options, making it easier for users to understand and interact with the available choices.

#### Switch group expression fields
<a name="switch-group-expression-fields"></a>
+ `{{ui.switchGroupID.value}}`: Returns an array of strings containing the value of each switch that is enabled by the app user.

### Checkbox group
<a name="checkbox-group-component"></a>

The **Checkbox group** component presents users with a group of checkboxes, allowing them to select multiple options simultaneously. It is useful when you want to provide users with the ability to choose one or more items from a list of options.

#### Checkbox group expression fields
<a name="checkbox-group-expression-fields"></a>
+ `{{ui.checkboxGroupID.value}}`: Returns an array of strings containing the value of each checkbox that is selected by the app user.

### Radio group
<a name="radio-group-component"></a>

The **Radio group** component is a set of radio buttons that allow users to select a single option from multiple mutually exclusive choices. It ensures that only one option can be selected at a time, providing a clear and unambiguous way for users to make a selection.

#### Radio group expression fields
<a name="radio-group-expression-fields"></a>

The following fields can be used in expressions.
+ `{{ui.radioGroupID.value}}`: Returns the value of the radio button that is selected by the app user.

### Single select
<a name="single-select-component"></a>

The **Single select** component presents users with a list of options, from which they can select a single item. It is commonly used in scenarios where users need to make a choice from a predefined set of options, such as selecting a category, a location, or a preference.

#### Single select expression fields
<a name="single-select-expression-fields"></a>
+ `{{ui.singleSelectID.value}}`: Returns the value of the list item that is selected by the app user.

### Multi select
<a name="multi-select-component"></a>

The **Multi select** component is similar to the **Single select** component but allows users to select multiple options simultaneously from a list of choices. It is useful when users need to make multiple selections from a predefined set of options, such as selecting multiple tags, interests, or preferences.

#### Multi select expression fields
<a name="multi-select-expression-fields"></a>
+ `{{ui.multiSelectID.value}}`: Returns an array of strings containing the value of each list item that is selected by the app user.

## Buttons & navigation components
<a name="buttons-and-navigation-components"></a>

The application studio provides a variety of button and navigation components to allow users to trigger actions and navigate within your application.

### Button components
<a name="button-components"></a>

The available button components are:
+ Button
+ Outlined button
+ Icon button
+ Text button

These button components share the following common properties:

#### Content
<a name="button-content"></a>
+ **Button label**: The text to be displayed on the button.

#### Type
<a name="button-type"></a>
+ **Button**: A standard button.
+ **Outlined**: A button with an outlined style.
+ **Icon**: A button with an icon.
+ **Text**: A text-only button.

#### Size
<a name="button-size"></a>

The size of the button. Possible values are `Small`, `Medium`, and `Large`.

#### Icon
<a name="button-icon"></a>

You can select from a variety of icons to be displayed on the button, including:
+ Envelope Closed
+ Bell
+ Person
+ Hamburger Menu
+ Search
+ Info Circled
+ Gear
+ Chevron Left
+ Chevron Right
+ Dots Horizontal
+ Trash
+ Edit
+ Check
+ Close
+ Home
+ Plus

#### Triggers
<a name="button-triggers"></a>

When the button is clicked, you can configure one or more actions to be triggered. The available action types are:
+ **Basic**
  + Run component action: Executes a specific action within a component.
  + Navigate: Navigates to another page or view.
  + Invoke Data Action: Triggers a data-related action, such as creating, updating, or deleting a record.
+ **Advanced**
  + JavaScript: Runs custom JavaScript code.
  + Invoke Automation: Starts an existing automation or workflow.

#### JavaScript action button properties
<a name="button-examples-javascript"></a>

Select the `JavaScript` action type to run custom JavaScript code when the button is clicked.

##### Source code
<a name="button-source-code"></a>

In the `Source code` field, you can enter your JavaScript expression or function. For example:

```
return "Hello World";
```

This will simply return the string `Hello World` when the button is clicked.

##### Condition: Run if
<a name="button-run-if"></a>

You can also provide a boolean expression that determines whether the JavaScript action should be executed or not. This uses the following syntax:

```
{{ui.textinput1.value !== ""}}
```

In this example, the JavaScript action will only run if the value of the `textinput1` component is not an empty string.

By using these advanced trigger options, you can create highly customized button behaviors that integrate directly with your application's logic and data. This allows you to extend the built-in functionality of the buttons and tailor the user experience to your specific requirements.

**Note**  
Always thoroughly test your JavaScript actions to ensure they are functioning as expected.

### Hyperlink
<a name="hyperlink-component"></a>

The **Hyperlink** component provides a clickable link for navigating to external URLs or internal application routes.

#### Hyperlink properties
<a name="hyperlink-properties"></a>

##### Content
<a name="hyperlink-properties-content"></a>
+ **Hyperlink label**: The text to be displayed as the hyperlink label.

##### URL
<a name="hyperlink-properties-url"></a>

The destination URL for the hyperlink, which can be an external website or an internal application route.

##### Triggers
<a name="hyperlink-properties-triggers"></a>

When the hyperlink is clicked, you can configure one or more actions to be triggered. The available action types are the same as those for the button components.

## Date & time components
<a name="date-and-time-components"></a>

### Date
<a name="date-component"></a>

The **Date** component allows users to select and input dates.

The **Date** component shares several common properties with other components, such as `Name`, `Source`, and `Validation`. For more information on these properties, see [Common component properties](#common-properties).

In addition to the common properties, the **Date** component has the following specific properties:

#### Date properties
<a name="date-component-properties"></a>

##### Format
<a name="date-component-properties-format"></a>
+ **YYYY/MM/DD**, **DD/MM/YYYY**, **YYYY/MM/DD**, **YYYY/DD/MM**, **MM/DD**, **DD/MM**: The format in which the date should be displayed.

##### Value
<a name="date-component-properties-value"></a>
+ **YYYY-MM-DD**: The format in which the date value is stored internally.

##### Min date
<a name="date-component-properties-min-date"></a>
+ **YYYY-MM-DD**: The minimum date that can be selected.
**Note**  
This value must match the format of `YYYY-MM-DD`.

##### Max date
<a name="date-component-properties-max-date"></a>
+ **YYYY-MM-DD**: The maximum date that can be selected.
**Note**  
This value must match the format of `YYYY-MM-DD`.

##### Calendar type
<a name="date-component-properties-calendar-type"></a>
+ **1 Month**, **2 Months**: The type of calendar UI to display.

##### Disabled dates
<a name="date-component-properties-disabled-dates"></a>
+ **Source**: The data source for the dates that should be disabled. For example: None, Expression.
+ **Disabled dates**: An expression that determines which dates should be disabled, such as:
  + `{{currentRow.column}}`: Disables dates that match what this expression evaluates to.
  + `{{new Date(currentRow.dateColumn) < new Date("2023-01-01")}}`: Disables dates before January 1, 2023
  + `{{new Date(currentRow.dateColumn).getDay() === 0 || new Date(currentRow.dateColumn).getDay() === 6}}`: Disables weekends.

##### Behavior
<a name="date-component-properties-behavior"></a>
+ **Visible if**: An expression that determines the visibility of the **Date** component.
+ **Disable if**: An expression that determines whether the **Date** component should be disabled.

#### Validation
<a name="date-component-properties-validation"></a>

The **Validation** section allows you to define additional rules and constraints for the date input. By configuring these validation rules, you can ensure that the date values entered by users meet the specific requirements of your application. You can add the following types of validations:
+ **Required**: This toggle ensures that the user must enter a date value before submitting the form.
+ **Custom**: You can create custom validation rules using JavaScript expressions. For example:

  ```
  {{new Date(ui.dateInput.value) < new Date("2023-01-01")}}
  ```

  This expression checks if the entered date is before January 1, 2023. If the condition is true, the validation will fail.

  You can also provide a custom validation message to be displayed when the validation is not met:

  ```
  "Validation not met. The date must be on or after January 1, 2023."
  ```

By configuring these validation rules, you can ensure that the date values entered by users meet the specific requirements of your application.

#### Expressions and examples
<a name="date-component-expressions"></a>

The **Date** component provides the following expression field:
+ `{{ui.dateID.value}}`: Returns the date value entered by the user in the format `YYYY-MM-DD`.

### Time
<a name="time-component"></a>

The **Time** component allows users to select and input time values. By configuring the various properties of the **Time** component, you can create time input fields that meet the specific requirements of your application, such as restricting the selectable time range, disabling certain times, and controlling the component's visibility and interactivity.

#### Time properties
<a name="time-component-properties"></a>

The **Time** component shares several common properties with other components, such as `Name`, `Source`, and `Validation`. For more information on these properties, see [Common component properties](#common-properties).

In addition to the common properties, the **Time** component has the following specific properties:

##### Time intervals
<a name="time-component-properties-time-intervals"></a>
+ **5 minutes**, **10 minutes**, **15 minutes**, **20 minutes**, **25 minutes**, **30 minutes**, **60 minutes**: The intervals available for selecting the time.

##### Value
<a name="time-component-properties-value"></a>
+ **HH:MM AA**: The format in which the time value is stored internally.
**Note**  
This value must match the format of `HH:MM AA`.

##### Placeholder
<a name="time-component-properties-placeholder"></a>
+ **Calendar settings**: The placeholder text displayed when the time field is empty.

##### Min time
<a name="time-component-properties-min-time"></a>
+ **HH:MM AA**: The minimum time that can be selected.
**Note**  
This value must match the format of `HH:MM AA`.

##### Max time
<a name="time-component-properties-max-time"></a>
+ **HH:MM AA**: The maximum time that can be selected.
**Note**  
This value must match the format of `HH:MM AA`.

##### Disabled times
<a name="time-component-properties-disabled-times"></a>
+ **Source**: The data source for the times that should be disabled (e.g., None, Expression).
+ **Disabled times**: An expression that determines which times should be disabled, such as `{{currentRow.column}}`.

##### Disabled times configuration
<a name="disabled-times-configuration"></a>

You can use the **Disabled Times** section to specify which time values should be unavailable for selection.

##### Source
<a name="disabled-times-configuration-source"></a>
+ **None**: No times are disabled.
+ **Expression**: You can use a JavaScript expression to determine which times should be disabled, such as `{{currentRow.column}}`.

##### Example expression:
<a name="disabled-times-configuration-expression-example"></a>

```
{{currentRow.column === "Lunch Break"}}
```

This expression would disable any times where the "Lunch Break" column is true for the current row.

By configuring these validation rules and disabled time expressions, you can ensure that the time values entered by users meet the specific requirements of your application.

##### Behavior
<a name="time-component-properties-behavior"></a>
+ **Visible if**: An expression that determines the visibility of the Time component.
+ **Disable if**: An expression that determines whether the Time component should be disabled.

##### Validation
<a name="time-component-properties-validation"></a>
+ **Required**: A toggle that ensures the user must enter a time value before submitting the form.
+ **Custom**: Allows you to create custom validation rules using JavaScript expressions.

  **Custom Validation Message**: The message to be displayed when the custom validation is not met.

For example:

```
{{ui.timeInput.value === "09:00 AM" || ui.timeInput.value === "09:30 AM"}}
```

This expression checks if the entered time is 9:00 AM or 9:30 AM. If the condition is true, the validation will fail.

You can also provide a custom validation message to be displayed when the validation is not met:

```
Validation not met. The time must be 9:00 AM or 9:30 AM.
```

#### Expressions and examples
<a name="time-component-expressions"></a>

The Time component provides the following expression field:
+ `{{ui.timeID.value}}`: Returns the time value entered by the user in the format HH:MM AA.

##### Example: Time value
<a name="time-component-expressions-examples-time-value"></a>
+ `{{ui.timeID.value}}`: Returns the time value entered by the user in the format `HH:MM AA`.

##### Example: Time comparison
<a name="time-component-expressions-examples-time-comparison"></a>
+ `{{ui.timeInput.value > "10:00 AM"}}`: Checks if the time value is greater than 10:00 AM.
+ `{{ui.timeInput.value < "05:00 pM"}}`: Checks if the time value is less than 05:00 PM.

### Date range
<a name="date-range-component"></a>

The **Date range** component allows users to select and input a range of dates. By configuring the various properties of the Date Range component, you can create date range input fields that meet the specific requirements of your application, such as restricting the selectable date range, disabling certain dates, and controlling the component's visibility and interactivity.

#### Date range properties
<a name="date-range-component-properties"></a>

The **Date Range** component shares several common properties with other components, such as `Name`, `Source`, and `Validation`. For more information on these properties, see [Common component properties](#common-properties).

In addition to the common properties, the **Date Range** component has the following specific properties:

##### Format
<a name="date-range-component-properties-format"></a>
+ **MM/DD/YYYY**: The format in which the date range should be displayed.

##### Start date
<a name="date-range-component-properties-start-date"></a>
+ **YYYY-MM-DD**: The minimum date that can be selected as the start of the range.
**Note**  
This value must match the format of `YYYY-MM-DD`.

##### End date
<a name="date-range-component-properties-end-date"></a>
+ **YYYY-MM-DD**: The maximum date that can be selected as the end of the range.
**Note**  
This value must match the format of `YYYY-MM-DD`.

##### Placeholder
<a name="date-range-component-properties-placeholder"></a>
+ **Calendar settings**: The placeholder text displayed when the date range field is empty.

##### Min date
<a name="date-range-component-properties-min-date"></a>
+ **YYYY-MM-DD**: The minimum date that can be selected.
**Note**  
This value must match the format of `YYYY-MM-DD`.

##### Max date
<a name="date-range-component-properties-max-date"></a>
+ **YYYY-MM-DD**: The maximum date that can be selected.
**Note**  
This value must match the format of `YYYY-MM-DD`.

##### Calendar type
<a name="date-range-component-properties-calendar-type"></a>
+ **1 Month**: The type of calendar UI to display. For example, single month.
+ **2 Month**: The type of calendar UI to display. For example, two months.

##### Mandatory days selected
<a name="date-range-component-properties-mandatory-days-selected"></a>
+ **0**: The number of mandatory days that must be selected within the date range.

##### Disabled dates
<a name="date-range-component-properties-disabled-dates"></a>
+ **Source**: The data source for the dates that should be disabled (e.g., None, Expression, Entity, or Automation).
+ **Disabled dates**: An expression that determines which dates should be disabled, such as `{{currentRow.column}}`.

##### Validation
<a name="date-range-component-properties-validation"></a>

The **Validation** section allows you to define additional rules and constraints for the date range input.

#### Expressions and examples
<a name="date-range-component-expressions"></a>

The **Date Range** component provides the following expression fields:
+ `{{ui.dateRangeID.startDate}}`: Returns the start date of the selected range in the format `YYYY-MM-DD`.
+ `{{ui.dateRangeID.endDate}}`: Returns the end date of the selected range in the format `YYYY-MM-DD`.

##### Example: Calculating date difference
<a name="date-range-component-expressions-examples-calculating-date-difference"></a>
+ `{(new Date(ui.dateRangeID.endDate) - new Date(ui.dateRangeID.startDate)) / (1000 * 60 * 60 * 24)}}` Calculates the number of days between the start and end dates.

##### Example: Conditional visibility based on date range
<a name="date-range-component-expressions-examples-conditional-visibility-based-on-date-range"></a>
+ `{{new Date(ui.dateRangeID.startDate) < new Date("2023-01-01") || new Date(ui.dateRangeID.endDate) > new Date("2023-12-31")}}` Checks if the selected date range is outside of the year 2023.

##### Example: Disabled dates based on current row data
<a name="date-range-component-expressions-examples-disabled-dates-based-on-current-row-data"></a>
+ `{{currentRow.isHoliday}}` Disables dates where the "isHoliday" column in the current row is true.
+ `{{new Date(currentRow.dateColumn) < new Date("2023-01-01")}}` Disables dates before January 1, 2023 based on the "dateColumn" in the current row.
+ `{{new Date(currentRow.dateColumn).getDay() === 0 || new Date(currentRow.dateColumn).getDay() === 6}}` Disables weekends based on the "dateColumn" in the current row.

##### Custom validation
<a name="date-range-component-expressions-examples-custom-validation"></a>
+ `{{new Date(ui.dateRangeID.startDate) > new Date(ui.dateRangeID.endDate)}}` Checks if the start date is later than the end date, which would fail the custom validation.

## Media components
<a name="media-components"></a>

The application studio provides several components for embedding and displaying various media types within your application.

### iFrame embed
<a name="iframe-embed-component"></a>

The **iFrame embed** component allows you to embed external web content or applications within your application using an iFrame.

#### iFrame embed properties
<a name="iframe-embed-properties"></a>

##### URL
<a name="iframe-embed-properties-iframe-url"></a>

**Note**  
The source of the media displayed in this component must be allowed in your application's content security settings. For more information, see [Viewing or updating your app's content security settings](app-content-security-settings-csp.md).

The URL of the external content or application you want to embed.

##### Layout
<a name="iframe-embed-properties-iframe-layout"></a>
+ **Width**: The width of the iFrame, specified as a percentage (%) or a fixed pixel value (e.g., 300px).
+ **Height**: The height of the iFrame, specified as a percentage (%) or a fixed pixel value.

### S3 upload
<a name="s3-upload-component"></a>

The **S3 upload** component allows users to upload files to an Amazon S3 bucket. By configuring the **S3 Upload** component, you can enable users to easily upload files to your application's Amazon S3 storage, and then leverage the uploaded file information within your application's logic and user interface.

**Note**  
Remember to ensure that the necessary permissions and Amazon S3 bucket configurations are in place to support the file uploads and storage requirements of your application.

#### S3 upload properties
<a name="s3-upload-properties"></a>

##### S3 Configuration
<a name="s3-upload-component-properties-configuration"></a>
+ **Connector**: Select the pre-configured Amazon S3 connector to use for the file uploads.
+ **Bucket**: The Amazon S3 bucket where the files will be uploaded.
+ **Folder**: The folder within the Amazon S3 bucket where the files will be stored.
+ **File name**: The naming convention for the uploaded files.

##### File upload configuration
<a name="s3-upload-component-properties-file-upload-configuration"></a>
+ **Label**: The label or instructions displayed above the file upload area.
+ **Description**: Additional instructions or information about the file upload.
+ **File type**: The type of files that are allowed to be uploaded. For example: image, document, or video.
+ **Size**: The maximum size of the individual files that can be uploaded.
+ **Button label**: The text displayed on the file selection button.
+ **Button style**: The style of the file selection button. For example, outlined or filled.
+ **Button size**: The size of the file selection button.

##### Validation
<a name="s3-upload-component-properties-validation"></a>
+ **Max number of files**: The maximum number of files that can be uploaded at once.
+ **Max file size**: The maximum size allowed for each individual file.

##### Triggers
<a name="s3-upload-component-properties-triggers"></a>
+ **On success**: Actions to be triggered when a file upload is successful.
+ **On failure**: Actions to be triggered when a file upload fails.

#### S3 upload expression fields
<a name="s3-upload-expression-fields"></a>

The **S3 upload** component provides the following expression fields:
+ `{{ui.s3uploadID.files}}`: Returns an array of the files that have been uploaded.
+ `{{ui.s3uploadID.files[0]?.size}}`: Returns the size of the file at the designated index.
+ `{{ui.s3uploadID.files[0]?.type}}`: Returns the type of the file at the designated index.
+ `{{ui.s3uploadID.files[0]?.nameOnly}}`: Returns the name of the file, with no extension suffix, at the designated index.
+ `{{ui.s3uploadID.files[0]?.nameWithExtension}}`: Returns the name of the file with its extension suffix at the designated index.

#### Expressions and examples
<a name="s3-upload-component-expression-examples"></a>

##### Example: Accessing uploaded files
<a name="s3-upload-component-expression-examples-accessing-uploaded-files"></a>
+ `{{ui.s3uploadID.files.length}}`: Returns the number of files that have been uploaded.
+ `{{ui.s3uploadID.files.map(f => f.name).join(', ')}}`: Returns a comma-separated list of the file names that have been uploaded.
+ `{{ui.s3uploadID.files.filter(f => f.type.startsWith('image/'))}}`: Returns an array of only the image files that have been uploaded.

##### Example: Validating file uploads
<a name="s3-upload-component-expression-examples-validating-file-uploads"></a>
+ `{{ui.s3uploadID.files.some(f => f.size > 5 * 1024 * 1024)}}`: Checks if any of the uploaded files exceed 5 MB in size.
+ `{{ui.s3uploadID.files.every(f => f.type === 'image/png')}}`: Checks if all the uploaded files are PNG images.
+ `{{ui.s3uploadID.files.length > 3}}`: Checks if more than 3 files have been uploaded.

##### Example: Triggering actions
<a name="s3-upload-component-expression-examples-triggering-actions"></a>
+ `{{ui.s3uploadID.files.length > 0 ? 'Upload Successful' : 'No files uploaded'}}`: Displays a success message if at least one file has been uploaded.
+ `{{ui.s3uploadID.files.some(f => f.type.startsWith('video/')) ? triggerVideoProcessing() : null}}`: Triggers a video processing automation if any video files have been uploaded.
+ `{{ui.s3uploadID.files.map(f => f.url)}}`: Retrieves the URLs of the uploaded files, which can be used to display or further process the files.

These expressions allow you to access the uploaded files, validate the file uploads, and trigger actions based on the file upload results. By utilizing these expressions, you can create more dynamic and intelligent behavior within your application's file upload functionality.

**Note**  
Replace *s3uploadID* with the ID of your **S3 upload** component.

### PDF viewer component
<a name="pdf-viewer-component"></a>

The **PDF viewer** component allows users to view and interact with PDF documents within your application. App Studio supports these different input types for the PDF Source, the **PDF viewer** component provides flexibility in how you can integrate PDF documents into your application, whether it's from a static URL, an inline data URI, or dynamically generated content.

#### PDF viewer properties
<a name="pdf-viewer-properties"></a>

##### Source
<a name="pdf-viewer-properties-source"></a>

**Note**  
The source of the media displayed in this component must be allowed in your application's content security settings. For more information, see [Viewing or updating your app's content security settings](app-content-security-settings-csp.md).

The source of the PDF document, which can be an expression, entity, URL, or automation.

##### Expression
<a name="pdf-viewer-properties-source-expression"></a>

Use an expression to dynamically generate the PDF source.

##### Entity
<a name="pdf-viewer-properties-source-entity"></a>

Connect the **PDF viewer** component to a data entity that contains the PDF document.

##### URL
<a name="pdf-viewer-properties-source-url"></a>

Specify the URL of the PDF document.

##### URL
<a name="pdf-viewer-properties-source-url-example"></a>

You can enter a URL that points to the PDF document you want to display. This could be a public web URL or a URL within your own application.

Example: `https://example.com/document.pdf`

##### Data URI
<a name="pdf-viewer-properties-source-url-data-uri"></a>

A **Data URI** is a compact way to include small data files (like images or PDFs) inline within your application. The PDF document is encoded as a base64 string and included directly in the component's configuration.

##### Blob or ArrayBuffer
<a name="pdf-viewer-properties-source-url-blob-or-arraybuffer"></a>

You can also provide the PDF document as a Blob or ArrayBuffer object, which allows you to dynamically generate or retrieve the PDF data from various sources within your application.

##### Automation
<a name="pdf-viewer-properties-source-automation"></a>

Connect the **PDF viewer** component to an automation that provides the PDF document.

##### Actions
<a name="pdf-viewer-properties-actions"></a>
+ **Download**: Adds a button or link that allows users to download the PDF document.

##### Layout
<a name="pdf-viewer-properties-layout"></a>
+ **Width**: The width of the PDF Viewer, specified as a percentage (%) or a fixed pixel value (e.g., 600px).
+ **Height**: The height of the PDF Viewer, specified as a fixed pixel value.

### Image viewer
<a name="image-viewer-component"></a>

The **Image viewer** component allows users to view and interact with image files within your application.

#### Image viewer properties
<a name="image-viewer-properties"></a>

##### Source
<a name="image-viewer-properties-source"></a>

**Note**  
The source of the media displayed in this component must be allowed in your application's content security settings. For more information, see [Viewing or updating your app's content security settings](app-content-security-settings-csp.md).
+ **Entity**: Connect the **Image viewer** component to a data entity that contains the image file.
+ **URL**: Specify the URL of the image file.
+ **Expression**: Use an expression to dynamically generate the image source.
+ **Automation**: Connect the **Image viewer** component to an automation that provides the image file.

##### Alt text
<a name="image-viewer-properties-alt-text"></a>

The alternative text description of the image, which is used for accessibility purposes.

##### Layout
<a name="image-viewer-properties-layout"></a>
+ **Image fit**: Determines how the image should be resized and displayed within the component. For example: `Contain`, `Cover`, or `Fill`.
+ **Width**: The width of the **Image viewer** component, specified as a percentage (%) or a fixed pixel value (e.g., 300px).
+ **Height**: The height of the **Image viewer** component, specified as a fixed pixel value.
+ **Background**: Allows you to set a background color or image for the **Image viewer** component.

# Automations and actions: Define your app's business logic
<a name="automations"></a>

**Automations** are how you define the business logic of your application. The main components of an automation are: triggers that start the automation, a sequence of one or more actions, input parameters used to pass data to the automation, and an output.

**Topics**
+ [Automations concepts](automations-concepts.md)
+ [Creating, editing, and deleting automations](automations-create-edit-delete.md)
+ [Adding, editing, and deleting automation actions](automations-actions-add-edit-delete.md)
+ [Automation actions reference](automations-actions-reference.md)

# Automations concepts
<a name="automations-concepts"></a>

Here are some concepts and terms to know when defining and configuring your app's business logic using automations in App Studio.

## Automations
<a name="automations-concepts-automations"></a>

**Automations** are how you define the business logic of your application. The main components of an automation are: triggers that start the automation, a sequence of one or more actions, input parameters used to pass data to the automation, and an output.

## Actions
<a name="automations-concepts-actions"></a>

An automation action, commonly referred to as an **action**, is an individual step of logic that make up an automation. Each action performs a specific task, whether it's sending an email, creating a data record, invoking a Lambda function, or calling APIs. Actions are added to automations from the action library, and can be grouped into conditional statements or loops.

## Automation input parameters
<a name="automations-concepts-parameters"></a>

**Automation input parameters** are dynamic input values that you can pass in from components to automations to make them flexible and reusable. Think of parameters as variables for your automation, instead of hard-coding values into an automation, you can define parameters and provide different values when needed. Parameters allow you to use the same automation with different inputs each time it is run. 

## Mocked output
<a name="automations-concepts-mocked-output"></a>

Some actions interact with external resources or services using connectors. When using the preview environment, applications do not interact with external services. To test actions that use connectors in the preview environment, you can use **mocked output** to simulate the connector's behavior and output. The mocked output is configured using JavaScript, and the result is stored in an action's results, just as the connector's response is stored in a published app.

By using mocking, you can use the preview environment to test various scenarios and their impact on other actions with the automation such as simulating different result values, error scenarios, edge cases, or unhappy paths without calling the external service through connectors.

## Automation output
<a name="automations-concepts-automation-output"></a>

An **automation output** is used to pass values from one automation to other resources of an app, such as components or other automations. Automation outputs are configured as expressions, and the expression can return a static value or a dynamic value computed from automation parameters and actions. By default, automations do not return any data, including the results of actions within the automation.

A couple of examples of how automation outputs can be used:
+ You can configure an automation output to return an array, and pass that array to populate a data component.
+ You can use an automation to calculate a value, and pass that value into multiple other automations as a way to centralize and reuse business logic.

## Triggers
<a name="automations-concepts-triggers"></a>

A **trigger** determines when, and on what conditions, an automation will run. Some examples of triggers are `On click` for buttons and `On select` for text inputs. The type of component determines the list of available triggers for that component. Triggers are added to [components](concepts.md#concepts-component) and configured in the application studio. 

# Creating, editing, and deleting automations
<a name="automations-create-edit-delete"></a>

**Contents**
+ [Creating an automation](#automations-create)
+ [Viewing or editing automation properties](#automations-edit)
+ [Deleting an automation](#automations-delete)

## Creating an automation
<a name="automations-create"></a>

Use the following procedure to create an automation in an App Studio application. Once created, an automation must be configured by editing its properties and adding actions to it.

**To create an automation**

1. If necessary, navigate to the application studio of your application.

1. Choose the **Automations** tab.

1. If you have no automations, choose **\$1 Add automation** in the canvas. Otherwise, in the left-side **Automations** menu, choose **\$1 Add**.

1. A new automation will be created, and you can start editing its properties or adding and configuring actions to define your application's business logic.

## Viewing or editing automation properties
<a name="automations-edit"></a>

Use the following procedure to view or edit automation properties.

**To view or edit automation properties**

1. If necessary, navigate to the application studio of your application.

1. Choose the **Automations** tab.

1. In the left-hand **Automations** menu, choose the automation for which you want to view or edit properties to open the right-side **Properties** menu.

1. In the **Properties** menu, you can view the following properties:
   + **Automation identifier**: The unique name of the automation. To edit it, enter a new identifier in the text field.
   + **Automation parameters**: Automation parameters are used to pass dynamic values from your app's UI to automation and data actions. To add a parameter, choose **\$1 Add**. Choose the pencil icon to change the parameter's name, description, or type. To remove a parameter, choose the trash icon.
**Tip**  
You can also add automation parameters directly from the canvas.
   + **Automation output**: The automation output is used to configure which data from the automation can be referenced in other automations or components. By default, automations do not create an output. To add an automation output choose **\$1 Add**. To remove the output, choose the trash icon.

1. You define what an automation does by adding and configuring actions. For more information about actions, see [Adding, editing, and deleting automation actions](automations-actions-add-edit-delete.md) and [Automation actions reference](automations-actions-reference.md).

## Deleting an automation
<a name="automations-delete"></a>

Use the following procedure to delete an automation in an App Studio application.

**To delete an automation**

1. If necessary, navigate to the application studio of your application.

1. Choose the **Automations** tab.

1. In the left-side **Automations** menu, choose the ellipses menu of the automation you want to delete, and choose **Delete**. Alternatively, you can choose the trash icon from the right-side **Properties** menu of the automation.

1. In the confirmation dialog box, choose **Delete**.

# Adding, editing, and deleting automation actions
<a name="automations-actions-add-edit-delete"></a>

An automation action, commonly referred to as an **action**, is an individual step of logic that make up an automation. Each action performs a specific task, whether it's sending an email, creating a data record, invoking a Lambda function, or calling APIs. Actions are added to automations from the action library, and can be grouped into conditional statements or loops.

**Contents**
+ [Adding an automation action](#automations-actions-add)
+ [Viewing and editing automation action properties](#automations-actions-edit)
+ [Deleting an automation action](#automations-actions-delete)

## Adding an automation action
<a name="automations-actions-add"></a>

Use the following procedure to add an action to an automation in an App Studio application.

**To add an automation action**

1. If necessary, navigate to the application studio of your application.

1. Choose the **Automations** tab.

1. In the left-side **Automations** menu, choose the automation you want to add an action to.

1. In the right-hand **Action** menu, choose the action you want to add, or drag and drop the action into the canvas. After the action is created, you can choose the action to configure the action properties to define the action's functionality. For more information about action properties and configuring them, see [Automation actions reference](automations-actions-reference.md).

## Viewing and editing automation action properties
<a name="automations-actions-edit"></a>

Use the following procedure to view or edit an automation action's properties in an App Studio application.

**To view or edit automation action properties**

1. If necessary, navigate to the application studio of your application.

1. Choose the **Automations** tab.

1. In the left-side **Automations** menu, choose the action of which you want to view or edit properties. Alternatively, you can choose the action in the canvas when viewing the automation that contains it.

1. You can view or edit the action properties in the right-side **Properties** menu. The properties for an action are different for each action type. For more information about action properties and configuring them, see [Automation actions reference](automations-actions-reference.md).

## Deleting an automation action
<a name="automations-actions-delete"></a>

Use the following procedure to delete an action from an automation in an App Studio application.

**To delete an automation action**

1. If necessary, navigate to the application studio of your application.

1. Choose the **Automations** tab.

1. In the left-side **Automations** menu, choose the automation that contains the action you want to delete.

1. In the canvas, choose the trash icon in the action you want to delete and choose **Delete**.

# Automation actions reference
<a name="automations-actions-reference"></a>

The following is the reference documentation for automation actions used in App Studio.

An automation action, commonly referred to as an **action**, is an individual step of logic that make up an automation. Each action performs a specific task, whether it's sending an email, creating a data record, invoking a Lambda function, or calling APIs. Actions are added to automations from the action library, and can be grouped into conditional statements or loops.

For information about creating and configuring automations and their actions, see the topics in [Automations and actions: Define your app's business logic](automations.md).

## Invoke API
<a name="automations-actions-reference-invoke-API"></a>

Invokes an HTTP REST API request. Builders can use this action to send requests from App Studio to other systems or services with APIs. For example, you could use it to connect to third-party systems or homegrown applications to access business critical data, or invoke API endpoints that cannot be called by dedicated App Studio actions.

For more information about REST APIs, see [What is a RESTful API?](https://aws.amazon.com/what-is/restful-api/).

### Properties
<a name="automations-actions-reference-invoke-API-properties"></a>

#### Connector
<a name="automations-actions-reference-invoke-API-properties-connector"></a>

The **Connector** to use for the API requests made by this action. The connector dropdown only contains connectors of the following types: `API Connector` and `OpenAPI Connector`. Depending on how the connector is configured, it can contain important information such as credentials and default headers or query parameters.

For more information about API connectors, including a comparison between using `API Connector` and `OpenAPI Connector`, see [Connect to third-party services](add-connector-third-party.md).

#### API request configuration properties
<a name="automations-actions-reference-invoke-API-properties-request-config"></a>

Choose **Configure API request** from the properties panel to open the request configuration dialog box. If an **API connector** is selected, the dialog box will include connector information.

**Method:** The method for the API call. Possible values are as follows:
+ `DELETE`: Deletes a specified resource.
+ `GET`: Retrieves information or data.
+ `HEAD`: Retrieves only the headers of a response without the body.
+ `POST`: Submits data to be processed.
+ `PUSH`: Submits data to be processed.
+ `PATCH`: Partially updates a specified resource.

**Path:** The relative path to the resource.

**Headers:** Any headers in the form of key-value pairs to be sent with the API request. If a connector is selected, its configured headers will be automatically added and cannot be removed. The configured headers cannot be edited, but you can override them by adding another header with the same name.

**Query parameters:** Any query parameters in the form of key-value pairs to be sent with the API request. If a connector is selected, its configured query parameters will be automatically added and cannot be edited or removed.

**Body:** Information to be sent with the API request in JSON format. There is no body for `GET` requests.

#### Mocked output
<a name="automations-actions-reference-invoke-API-properties-mocked-output"></a>

Actions do not interact with external services or resources in the preview environment. The **Mocked output** field is used to provide a JSON expression that simulates the behavior of a connector in the preview environment for testing purposes. This snippet is stored in the action's `results` map, just like the connector response would be for a published app in the live environment.

With this field, you can test various scenarios and their impact on other actions within the automation such as simulating different result values, error scenarios, edge cases, or unhappy paths without communicating with external services through connectors.

## Invoke AWS
<a name="automations-actions-reference-invoke-aws"></a>

Invokes an operation from an AWS service. This is a general action for calling AWS services or operations, and should be used if there is not a dedicated action for the desired AWS service or operation.

### Properties
<a name="automations-actions-reference-invoke-aws-properties"></a>

#### Service
<a name="automations-actions-reference-invoke-aws-properties-service"></a>

The AWS service which contains the operation to be run.

#### Operation
<a name="automations-actions-reference-invoke-aws-properties-operation"></a>

The operation to be run.

#### Connector
<a name="automations-actions-reference-invoke-aws-properties-connector"></a>

The connector to be used for the operations run by this action. The configured connector should be set up with the proper credentials to run the operation, and other configuration information, such as the AWS region that contains any resources referenced in the operation.

#### Configuration
<a name="automations-actions-reference-invoke-aws-properties-configuration"></a>

The JSON input to be when running the specified operation. For more information about configuring inputs for AWS operations, see the [AWS SDK for JavaScript](https://docs.aws.amazon.com/sdk-for-javascript).

## Invoke Lambda
<a name="automations-actions-reference-invoke-lambda"></a>

Invokes an existing Lambda function.

### Properties
<a name="automations-actions-reference-invoke-lambda-properties"></a>

#### Connector
<a name="automations-actions-reference-invoke-lambda-properties-connector"></a>

The connector to be used for the Lambda functions run by this action. The configured connector should be set up with the proper credentials to access the Lambda function, and other configuration information, such as the AWS region that contains the Lambda function. For more information about configuring a connector for Lambda, see [Step 3: Create Lambda connector](connectors-lambda.md#connectors-lambda-create-connector).

#### Function name
<a name="automations-actions-reference-invoke-lambda-properties-function-name"></a>

The name of the Lambda function to be run. Note that this is the function name, and not the function ARN (Amazon Resource Name).

#### Function event
<a name="automations-actions-reference-invoke-lambda-properties-function-event"></a>

Key-value pairs to be passed along to your Lambda function as the event payload.

#### Mocked output
<a name="automations-actions-reference-invoke-lambda-properties-mocked-output"></a>

Actions do not interact with external services or resources in the preview environment. The **Mocked output** field is used to provide a JSON expression that simulates the behavior of a connector in the preview environment for testing purposes. This snippet is stored in the action's `results` map, just like the connector response would be for a published app in the live environment.

With this field, you can test various scenarios and their impact on other actions within the automation such as simulating different result values, error scenarios, edge cases, or unhappy paths without communicating with external services through connectors.

## Loop
<a name="automations-actions-reference-loop"></a>

Runs nested actions repeatedly to iterate through a list of items, one item at a time. For example, add the [Create record](#automations-actions-reference-create-record) action to a loop action to create multiple records.

The loop action can be nested within other loops or condition actions. The loop actions are run sequentially, and not in parallel. The results of each action within the loop can only be accessed to subsequent actions within the same loop iteration. They cannot be accessed outside of the loop or in different iterations of the loop.

### Properties
<a name="automations-actions-reference-loop-properties"></a>

#### Source
<a name="automations-actions-reference-loop-properties-source"></a>

The list of items to iterate through, one item at a time. The source can be the result of a previous action or a static list of strings, numbers, or objects that you can provide using a JavaScript expression.

##### Examples
<a name="automations-actions-reference-loop-properties-source-examples"></a>

The following list contains examples of source inputs.
+ Results from a previous action: `{{results.actionName.data}}`
+ A list of numbers: `{{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}}`
+ A list of strings: `{{["apple", "banana", "orange", "grape", "kiwi"]}}`
+ A computed value: `{{params.actionName.split("\n")}}`

#### Current item name
<a name="automations-actions-reference-loop-properties-function-name"></a>

The name of the variable that can be used to reference the current item being iterated. The current item name is configurable so that you can nest two or more loops and access variables from each loop. For example, if you are looping through countries and cities with two loops, you could configure and reference `currentCountry` and `currentCity`.

## Condition
<a name="automations-actions-reference-condition"></a>

Runs actions based on the result of one or more specified logical conditions that are evaluated when the automation is run. The condition action is made up of the following components:
+ A *condition* field, which is used to provide a JavaScript expression that evaluates to `true` or `false`.
+ A *true branch*, which contains actions that are run if the condition evalutes to `true`.
+ A *false branch*, which contains actions that are run if the condition evalutes to `false`.

Add actions to the true and false branches by dragging them into the condition action.

### Properties
<a name="automations-actions-reference-condition-properties"></a>

#### Condition
<a name="automations-actions-reference-condition-properties-condition"></a>

The JavaScript expression to be evaluated when the action is run.

## Create record
<a name="automations-actions-reference-create-record"></a>

Creates one record in an existing App Studio entity.

### Properties
<a name="automations-actions-reference-create-record-properties"></a>

#### Entity
<a name="automations-actions-reference-create-record-properties-entity"></a>

The entity in which a record is to be created. Once an entity is selected, values must be added to the entity's fields for the record to be created. The types of the fields, and if the fields are required or optional are defined in the entity.

## Update record
<a name="automations-actions-reference-update-record"></a>

Updates an existing record in an App Studio entity.

### Properties
<a name="automations-actions-reference-update-record-properties"></a>

#### Entity
<a name="automations-actions-reference-update-record-properties-entity"></a>

The entity that contains the records to be updated.

#### Conditions
<a name="automations-actions-reference-update-record-properties-conditions"></a>

The criteria that defines which records are updated by the action. You can group conditions to create one logical statement. You can combine groups or conditions with `AND` or `OR` statements.

#### Fields
<a name="automations-actions-reference-update-record-properties-fields"></a>

The fields to be updated in the records specified by the conditions.

#### Values
<a name="automations-actions-reference-update-record-properties-values"></a>

The values to be updated in the specified fields.

## Delete record
<a name="automations-actions-reference-delete-record"></a>

Deletes a record from an App Studio entity.

### Properties
<a name="automations-actions-reference-delete-record-properties"></a>

#### Entity
<a name="automations-actions-reference-delete-record-properties-entity"></a>

The entity that contains the records to be deleted.

#### Conditions
<a name="automations-actions-reference-delete-record-properties-conditions"></a>

The criteria that defines which records are deleted by the action. You can group conditions to create one logic statement. You can combine groups or conditions with `AND` or `OR` statements.

## Invoke data action
<a name="automations-actions-reference-invoke-data-action"></a>

Runs a data action with optional parameters.

### Properties
<a name="automations-actions-reference-invoke-data-action-properties"></a>

#### Data action
<a name="automations-actions-reference-invoke-data-action-properties-data-action"></a>

The data action to be run by the action.

#### Parameters
<a name="automations-actions-reference-invoke-data-action-properties-parameters"></a>

Data action parameters to be used by the data action. Data action parameters are used to send values that are used as inputs for data actions. Data action parameters can be added when configuring the automation action, but must be edited in the **Data** tab.

#### Advanced settings
<a name="automations-actions-reference-invoke-data-action-properties-advanced-settings"></a>

The `Invoke data action` action contains the following advanced settings:
+ **Page size:** The maximum number of records to fetch in each query. The default value is 500, and the maximum value is 3000.
+ **Pagination token:** The token used to fetch additional records from a query. For example, if the `Page size` is set to 500, but there are more than 500 records, passing the pagination token to a subsequent query will fetch the next 500. The token will be undefined if no more records or pages exist.

## Amazon S3: Put object
<a name="automations-actions-reference-s3-put-object"></a>

Uses the `Amazon S3 PutObject` operation to add an object identified by a key (file path) to a specified Amazon S3 bucket.

### Properties
<a name="automations-actions-reference-s3-put-object-properties"></a>

#### Connector
<a name="automations-actions-reference-s3-put-object-properties-connector"></a>

The connector to be used for the operations run by this action. The configured connector should be set up with the appropriate credentials to run the operation, and other configuration information, such as the AWS region that contains any resources referenced in the operation.

#### Configuration
<a name="automations-actions-reference-s3-put-object-properties-configuration"></a>

The required options to be used in the `PutObject` command. The options are as follows:

**Note**  
For more information about the `Amazon S3 PutObject` operation, see [PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) in the *Amazon Simple Storage Service API Reference*.
+ **Bucket:** The name of the Amazon S3 bucket in which to put an object.
+ **Key:** The unique name of the object to be put into the Amazon S3 bucket.
+ **Body:** The content of the object to be put into the Amazon S3 bucket.

#### Mocked output
<a name="automations-actions-reference-s3-put-object-properties-mocked-output"></a>

Actions do not interact with external services or resources in the preview environment. The **Mocked output** field is used to provide a JSON expression that simulates the behavior of a connector in the preview environment for testing purposes. This snippet is stored in the action's `results` map, just like the connector response would be for a published app in the live environment.

With this field, you can test various scenarios and their impact on other actions within the automation such as simulating different result values, error scenarios, edge cases, or unhappy paths without communicating with external services through connectors.

## Amazon S3: Delete object
<a name="automations-actions-reference-s3-delete-object"></a>

Uses the `Amazon S3 DeleteObject` operation to delete an object identified by a key (file path) from a specified Amazon S3 bucket.

### Properties
<a name="automations-actions-reference-s3-delete-object-properties"></a>

#### Connector
<a name="automations-actions-reference-s3-delete-object-properties-connector"></a>

The connector to be used for the operations run by this action. The configured connector should be set up with the proper credentials to run the operation, and other configuration information, such as the AWS region that contains any resources referenced in the operation.

#### Configuration
<a name="automations-actions-reference-s3-delete-object-properties-configuration"></a>

The required options to be used in the `DeleteObject` command. The options are as follows:

**Note**  
For more information about the `Amazon S3 DeleteObject` operation, see [DeleteObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html) in the *Amazon Simple Storage Service API Reference*.
+ **Bucket:** The name of the Amazon S3 bucket from which to delete an object.
+ **Key:** The unique name of the object to be deleted from the Amazon S3 bucket.

#### Mocked output
<a name="automations-actions-reference-s3-delete-object-properties-mocked-output"></a>

Actions do not interact with external services or resources in the preview environment. The **Mocked output** field is used to provide a JSON expression that simulates the behavior of a connector in the preview environment for testing purposes. This snippet is stored in the action's `results` map, just like the connector response would be for a published app in the live environment.

With this field, you can test various scenarios and their impact on other actions within the automation such as simulating different result values, error scenarios, edge cases, or unhappy paths without communicating with external services through connectors.

## Amazon S3: Get object
<a name="automations-actions-reference-s3-get-object"></a>

Uses the `Amazon S3 GetObject` operation to retrieve an object identified by a key (file path) from a specified Amazon S3 bucket.

### Properties
<a name="automations-actions-reference-s3-get-object-properties"></a>

#### Connector
<a name="automations-actions-reference-s3-get-object-properties-connector"></a>

The connector to be used for the operations run by this action. The configured connector should be set up with the proper credentials to run the operation, and other configuration information, such as the AWS region that contains any resources referenced in the operation.

#### Configuration
<a name="automations-actions-reference-s3-get-object-properties-configuration"></a>

The required options to be used in the `GetObject` command. The options are as follows:

**Note**  
For more information about the `Amazon S3 GetObject` operation, see [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html) in the *Amazon Simple Storage Service API Reference*.
+ **Bucket:** The name of the Amazon S3 bucket from which to retrieve an object.
+ **Key:** The unique name of the object to be retrieved from the Amazon S3 bucket.

#### Mocked output
<a name="automations-actions-reference-s3-get-object-properties-mocked-output"></a>

Actions do not interact with external services or resources in the preview environment. The **Mocked output** field is used to provide a JSON expression that simulates the behavior of a connector in the preview environment for testing purposes. This snippet is stored in the action's `results` map, just like the connector response would be for a published app in the live environment.

With this field, you can test various scenarios and their impact on other actions within the automation such as simulating different result values, error scenarios, edge cases, or unhappy paths without communicating with external services through connectors.

## Amazon S3: List objects
<a name="automations-actions-reference-s3-list-objects"></a>

Uses the `Amazon S3 ListObjects` operation to list objects in a specified Amazon S3 bucket.

### Properties
<a name="automations-actions-reference-s3-list-objects-properties"></a>

#### Connector
<a name="automations-actions-reference-s3-list-objects-properties-connector"></a>

The connector to be used for the operations run by this action. The configured connector should be set up with the proper credentials to run the operation, and other configuration information, such as the AWS region that contains any resources referenced in the operation.

#### Configuration
<a name="automations-actions-reference-s3-list-objects-properties-configuration"></a>

The required options to be used in the `ListObjects` command. The options are as follows:

**Note**  
For more information about the `Amazon S3 ListObjects` operation, see [ListObjects](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html) in the *Amazon Simple Storage Service API Reference*.
+ **Bucket:** The name of the Amazon S3 bucket from which to list objects.

#### Mocked output
<a name="automations-actions-reference-s3-list-objects-properties-mocked-output"></a>

Actions do not interact with external services or resources in the preview environment. The **Mocked output** field is used to provide a JSON expression that simulates the behavior of a connector in the preview environment for testing purposes. This snippet is stored in the action's `results` map, just like the connector response would be for a published app in the live environment.

With this field, you can test various scenarios and their impact on other actions within the automation such as simulating different result values, error scenarios, edge cases, or unhappy paths without communicating with external services through connectors.

## Amazon Textract: Analyze document
<a name="automations-actions-reference-textract-analyze-document"></a>

Uses the `Amazon Textract AnalyzeDocument` operation to analyze an input document for relationships between detected items.

### Properties
<a name="automations-actions-reference-textract-analyze-document-properties"></a>

#### Connector
<a name="automations-actions-reference-textract-analyze-document-properties-connector"></a>

The connector to be used for the operations run by this action. The configured connector should be set up with the proper credentials to run the operation, and other configuration information, such as the AWS region that contains any resources referenced in the operation.

#### Configuration
<a name="automations-actions-reference-textract-analyze-document-properties-configuration"></a>

The content of the request to be used in the `AnalyzeDocument` command. The options are as follows:

**Note**  
For more information about the `Amazon Textract AnalyzeDocument` operation, see [AnalyzeDocument](https://docs.aws.amazon.com/textract/latest/dg/API_AnalyzeDocument.html) in the *Amazon Textract Developer Guide*.
+ **Document / S3Object / Bucket:** The name of the Amazon S3 bucket. This parameter can be left empty if a file is passed to the action with the **S3 upload** component.
+ **Document / S3Object / Name:** The file name of the input document. This parameter can be left empty if a file is passed to the action with the **S3 upload** component.
+ **Document / S3Object / Version:** If the Amazon S3 bucket has versioning enabled, you can specify the version of the object. This parameter can be left empty if a file is passed to the action with the **S3 upload** component.
+ **FeatureTypes:** A list of the types of analysis to perform. Valid values are: `TABLES`, `FORMS`, `QUERIES`, `SIGNATURES`, and `LAYOUT`.

#### Mocked output
<a name="automations-actions-reference-textract-analyze-document-properties-mocked-output"></a>

Actions do not interact with external services or resources in the preview environment. The **Mocked output** field is used to provide a JSON expression that simulates the behavior of a connector in the preview environment for testing purposes. This snippet is stored in the action's `results` map, just like the connector response would be for a published app in the live environment.

With this field, you can test various scenarios and their impact on other actions within the automation such as simulating different result values, error scenarios, edge cases, or unhappy paths without communicating with external services through connectors.

## Amazon Textract: Analyze expense
<a name="automations-actions-reference-textract-analyze-expense"></a>

Uses the `Amazon Textract AnalyzeExpense` operation to analyze an input document for financially-related relationships between text.

### Properties
<a name="automations-actions-reference-textract-analyze-expense-properties"></a>

#### Connector
<a name="automations-actions-reference-textract-analyze-expense-properties-connector"></a>

The connector to be used for the operations run by this action. The configured connector should be set up with the proper credentials to run the operation, and other configuration information, such as the AWS region that contains any resources referenced in the operation.

#### Configuration
<a name="automations-actions-reference-textract-analyze-expense-properties-configuration"></a>

The content of the request to be used in the `AnalyzeExpense` command. The options are as follows:

**Note**  
For more information about the `Amazon Textract AnalyzeExpense` operation, see [AnalyzeExpense](https://docs.aws.amazon.com/textract/latest/dg/API_AnalyzeExpense.html) in the *Amazon Textract Developer Guide*.
+ **Document / S3Object / Bucket:** The name of the Amazon S3 bucket. This parameter can be left empty if a file is passed to the action with the **S3 upload** component.
+ **Document / S3Object / Name:** The file name of the input document. This parameter can be left empty if a file is passed to the action with the **S3 upload** component.
+ **Document / S3Object / Version:** If the Amazon S3 bucket has versioning enabled, you can specify the version of the object. This parameter can be left empty if a file is passed to the action with the **S3 upload** component.

#### Mocked output
<a name="automations-actions-reference-textract-analyze-expense-properties-mocked-output"></a>

Actions do not interact with external services or resources in the preview environment. The **Mocked output** field is used to provide a JSON expression that simulates the behavior of a connector in the preview environment for testing purposes. This snippet is stored in the action's `results` map, just like the connector response would be for a published app in the live environment.

With this field, you can test various scenarios and their impact on other actions within the automation such as simulating different result values, error scenarios, edge cases, or unhappy paths without communicating with external services through connectors.

## Amazon Textract: Analyze ID
<a name="automations-actions-reference-textract-analyze-id"></a>

Uses the `Amazon Textract AnalyzeID` operation to analyze an identity document for relevant information.

### Properties
<a name="automations-actions-reference-textract-analyze-id-properties"></a>

#### Connector
<a name="automations-actions-reference-textract-analyze-id-properties-connector"></a>

The connector to be used for the operations run by this action. The configured connector should be set up with the proper credentials to run the operation, and other configuration information, such as the AWS region that contains any resources referenced in the operation.

#### Configuration
<a name="automations-actions-reference-textract-analyze-id-properties-configuration"></a>

The content of the request to be used in the `AnalyzeID` command. The options are as follows:

**Note**  
For more information about the `Amazon Textract AnalyzeID` operation, see [AnalyzeID](https://docs.aws.amazon.com/textract/latest/dg/API_AnalyzeID.html) in the *Amazon Textract Developer Guide*.
+ **Document / S3Object / Bucket:** The name of the Amazon S3 bucket. This parameter can be left empty if a file is passed to the action with the **S3 upload** component.
+ **Document / S3Object / Name:** The file name of the input document. This parameter can be left empty if a file is passed to the action with the **S3 upload** component.
+ **Document / S3Object / Version:** If the Amazon S3 bucket has versioning enabled, you can specify the version of the object. This parameter can be left empty if a file is passed to the action with the **S3 upload** component.

#### Mocked output
<a name="automations-actions-reference-textract-analyze-id-properties-mocked-output"></a>

Actions do not interact with external services or resources in the preview environment. The **Mocked output** field is used to provide a JSON expression that simulates the behavior of a connector in the preview environment for testing purposes. This snippet is stored in the action's `results` map, just like the connector response would be for a published app in the live environment.

With this field, you can test various scenarios and their impact on other actions within the automation such as simulating different result values, error scenarios, edge cases, or unhappy paths without communicating with external services through connectors.

## Amazon Textract: Detect doc text
<a name="automations-actions-reference-textract-detect-document-text"></a>

Uses the `Amazon Textract DetectDocumentText` operation to detect lines of text and the words that make up a line of text in an input document.

### Properties
<a name="automations-actions-reference-textract-detect-document-text-properties"></a>

#### Connector
<a name="automations-actions-reference-textract-detect-document-text-properties-connector"></a>

The connector to be used for the operations run by this action. The configured connector should be set up with the proper credentials to run the operation, and other configuration information, such as the AWS region that contains any resources referenced in the operation.

#### Configuration
<a name="automations-actions-reference-textract-detect-document-text-properties-configuration"></a>

The content of the request to be used in the `DetectDocumentText` command. The options are as follows:

**Note**  
For more information about the `Amazon Textract DetectDocumentText` operation, see [DetectDocumentText](https://docs.aws.amazon.com/textract/latest/dg/API_DetectDocumentText.html) in the *Amazon Textract Developer Guide*.
+ **Document / S3Object / Bucket:** The name of the Amazon S3 bucket. This parameter can be left empty if a file is passed to the action with the **S3 upload** component.
+ **Document / S3Object / Name:** The file name of the input document. This parameter can be left empty if a file is passed to the action with the **S3 upload** component.
+ **Document / S3Object / Version:** If the Amazon S3 bucket has versioning enabled, you can specify the version of the object. This parameter can be left empty if a file is passed to the action with the **S3 upload** component.

#### Mocked output
<a name="automations-actions-reference-textract-detect-document-text-properties-mocked-output"></a>

Actions do not interact with external services or resources in the preview environment. The **Mocked output** field is used to provide a JSON expression that simulates the behavior of a connector in the preview environment for testing purposes. This snippet is stored in the action's `results` map, just like the connector response would be for a published app in the live environment.

With this field, you can test various scenarios and their impact on other actions within the automation such as simulating different result values, error scenarios, edge cases, or unhappy paths without communicating with external services through connectors.

## Amazon Bedrock: GenAI Prompt
<a name="automations-actions-reference-bedrock-prompt"></a>

Uses the [Amazon Bedrock InvokeModel](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModel.html) operation to run inference using the prompt and inference parameters provided in the action properties. The action can generate text, images, and embeddings.

### Properties
<a name="automations-actions-reference-bedrock-prompt-properties"></a>

#### Connector
<a name="automations-actions-reference-bedrock-prompt-properties-connector"></a>

The connector to be used for the operations run by this action. To use this action successfully, the connector must be configured with **Amazon Bedrock Runtime** as the service. The configured connector should be set up with the proper credentials to run the operation, and other configuration information, such as the AWS region that contains any resources referenced in the operation.

#### Model
<a name="automations-actions-reference-bedrock-prompt-properties-model"></a>

The foundation model to be used by Amazon Bedrock to process the request. For more information about models in Amazon Bedrock, see [Amazon Bedrock foundation model information](https://docs.aws.amazon.com/bedrock/latest/userguide/foundation-models-reference.html) in the *Amazon Bedrock User Guide*.

#### Input type
<a name="automations-actions-reference-bedrock-prompt-properties-input-type"></a>

The input type of the input send to the Amazon Bedrock model. The possible values are **Text**, **Document**, and **Image**. If an input type is not available for selection, it is likely not supported by the configured model.

#### User prompt
<a name="automations-actions-reference-bedrock-prompt-properties-user-prompt"></a>

The prompt to be sent to the Amazon Bedrock model to be processed to generate a response. You can enter static text, or pass in an input from another part of your application, such as from a component using parameters, a previous action in the automation, or another automation. The following examples show how to pass in a value from a component or previous action:
+ To pass a value from a component using paramters: `{{params.paramName}}`
+ To pass a value from a previous action: `{{results.actionName}}`

#### System prompt (Claude models)
<a name="automations-actions-reference-bedrock-prompt-properties-system-prompt"></a>

The system prompt to be used by the Amazon Bedrock model when processing the request. The system prompt is used to provide context, instructions, or guidelines to Claude models.

#### Request settings
<a name="automations-actions-reference-bedrock-prompt-properties-request-settings"></a>

Configure various request settings and model inference parameters. You can configure the following settings:
+ **Temperature**: The temperature to be used by the Amazon Bedrock model when processing the request. The temperature determines the randomness or creativity of the Bedrock model's output. The higher the temperature, the more creative and less analytical the response will be. Possible values are `[0-10]`.
+ **Max Tokens**: Limit the length of the output of the Amazon Bedrock model.
+ **TopP**: In nucleus sampling, the model computes the cumulative distribution over all the options for each subsequent token in decreasing probability order and cuts it off once it reaches a particular probability specified by the **TopP**. You should alter either **temperature** or **TopP**, but not both
+ **Stop Sequences**: Sequences that cause the model to stop processing the request and generating output.

For more information, see [Inference request parameters and response fields for foundation models](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters.html) in the *Amazon Bedrock User Guide*.

#### Stop Sequences
<a name="automations-actions-reference-bedrock-prompt-properties-guardrail"></a>

Enter an Amazon Bedrock Guardrail **ID** and **Version**. Guardrails are used to implement safeguards based on your use cases and responsible AI policies. For more information, see [Stop harmful content in models using Amazon Bedrock Guardrails](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html) in the *Amazon Bedrock User Guide*.

#### Mocked output
<a name="automations-actions-reference-bedrock-prompt-properties-mocked-output"></a>

Actions do not interact with external services or resources in the preview environment. The **Mocked output** field is used to provide a JSON expression that simulates the behavior of a connector in the preview environment for testing purposes. This snippet is stored in the action's `results` map, just like the connector response would be for a published app in the live environment.

With this field, you can test various scenarios and their impact on other actions within the automation such as simulating different result values, error scenarios, edge cases, or unhappy paths without communicating with external services through connectors.

## Amazon Bedrock: Invoke model
<a name="automations-actions-reference-bedrock-invoke-model"></a>

Uses the [Amazon Bedrock InvokeModel](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModel.html) operation to run inference using the prompt and inference parameters provided in the request body. You use model inference to generate text, images, and embeddings.

### Properties
<a name="automations-actions-reference-bedrock-invoke-model-properties"></a>

#### Connector
<a name="automations-actions-reference-bedrock-invoke-model-properties-connector"></a>

The connector to be used for the operations run by this action. To use this action successfully, the connector must be configured with **Amazon Bedrock Runtime** as the service. The configured connector should be set up with the proper credentials to run the operation, and other configuration information, such as the AWS region that contains any resources referenced in the operation.

#### Configuration
<a name="automations-actions-reference-bedrock-invoke-model-properties-configuration"></a>

The content of the request to be used in the `InvokeModel` command.

**Note**  
For more information about the `Amazon Bedrock InvokeModel` operation, including example commands, see [InvokeModel](https://docs.aws.amazon.com/textract/latest/dg/API_DetectDocumentText.html) in the *Amazon Bedrock API Reference*.

#### Mocked output
<a name="automations-actions-reference-bedrock-invoke-model-properties-mocked-output"></a>

Actions do not interact with external services or resources in the preview environment. The **Mocked output** field is used to provide a JSON expression that simulates the behavior of a connector in the preview environment for testing purposes. This snippet is stored in the action's `results` map, just like the connector response would be for a published app in the live environment.

With this field, you can test various scenarios and their impact on other actions within the automation such as simulating different result values, error scenarios, edge cases, or unhappy paths without communicating with external services through connectors.

## JavaScript
<a name="automations-actions-reference-javascript"></a>

Runs a custom JavaScript function to return a specified value.

**Important**  
App Studio does not support using third-party or custom JavaScript libraries.

### Properties
<a name="automations-actions-reference-javascript-properties"></a>

#### Source code
<a name="automations-actions-reference-javascript-properties-source-code"></a>

The JavaScript code snippet to be run by the action.

**Tip**  
You can use AI to help generate JavaScript for you by performing the following steps:  
Choose the expand icon to open the expanded JavaScript editor.
(Optional): Enable the **Modify code** toggle to modify any existing JavaScript. Otherwise, AI will replace any existing JavaScript.
In **Generate JavaScript**, describe what you want to do with JavaScript, for example: **Add two numbers**.
Choose the send icon to generate your JavaScript.

## Invoke automation
<a name="automations-actions-reference-invoke-automation"></a>

Runs a specified automation.

### Properties
<a name="automations-actions-reference-invoke-automation-properties"></a>

#### Invoke Automation
<a name="automations-actions-reference-invoke-automation-properties-invoke-automation"></a>

The automation to be run by the action.

## Send email
<a name="automations-actions-reference-send-email"></a>

Uses the `Amazon SES SendEmail` operation to send an email.

### Properties
<a name="automations-actions-reference-send-email-properties"></a>

#### Connector
<a name="automations-actions-reference-send-email-properties-connector"></a>

The connector to be used for the operations run by this action. The configured connector should be set up with the proper credentials to run the operation, and other configuration information, such as the AWS region that contains any resources referenced in the operation.

#### Configuration
<a name="automations-actions-reference-send-email-properties-configuration"></a>

The content of the request to be used in the `SendEmail` command. The options are as follows:

**Note**  
For more information about the `Amazon SES SendEmail` operation, see [SendEmail](https://docs.aws.amazon.com/ses/latest/APIReference-V2/API_SendEmail.html) in the *Amazon Simple Email Service API Reference*.

#### Mocked output
<a name="automations-actions-reference-send-email-properties-mocked-output"></a>

Actions do not interact with external services or resources in the preview environment. The **Mocked output** field is used to provide a JSON expression that simulates the behavior of a connector in the preview environment for testing purposes. This snippet is stored in the action's `results` map, just like the connector response would be for a published app in the live environment.

With this field, you can test various scenarios and their impact on other actions within the automation such as simulating different result values, error scenarios, edge cases, or unhappy paths without communicating with external services through connectors.

# Entities and data actions: Configure your app's data model
<a name="data"></a>

**Entities** are data tables in App Studio. Entities interact directly with tables in data sources. Entities include fields to describe the data in them, queries to locate and return data, and mapping to connect the entity's fields to a data source's columns.

**Topics**
+ [Best practices when designing data models](data-model-best-practices.md)
+ [Creating an entity in an App Studio app](data-entities-create.md)
+ [Configuring or editing an entity in an App Studio app](data-entities-edit.md)
+ [Deleting an entity](data-entities-delete.md)
+ [Managed data entities in AWS App Studio](managed-data-entities.md)

# Best practices when designing data models
<a name="data-model-best-practices"></a>

Use the following best practices to create a robust, scalable, and secure relational data model in AWS for use in your App Studio application that meets your application's requirements and ensures the long-term reliability and performance of your data infrastructure.
+ **Choose the right AWS data service: ** Depending on your requirements, choose the appropriate AWS data service. For example, for an Online Transaction Processing (OLTP) application, you could consider a database (DB) such as Amazon Aurora which is a cloud-native, relational, and fully-managed database service that supports various database engines like MySQL and PostgreSQL. For a full list of Aurora versions supported by App Studio, see [Connect to Amazon Aurora](connectors-aurora.md). On the other hand, for Online Analytical Processing (OLAP) use cases, consider using Amazon Redshift, which is a cloud data warehouse that lets you run complex queries against very large datasets. These queries can often take time (many seconds) to complete, making Amazon Redshift less suitable for OLTP applications that require low-latency data access.
+ **Design for scalability: **Plan your data model with future growth and scalability in mind. Consider factors like expected data volume, access patterns, and performance requirements when choosing an appropriate data service and database instance type and configuration (such as provisioned capacity).
  + For more information about scaling with Aurora serverless, see [Performance and scaling for Aurora Serverless V2](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.setting-capacity.html).
+ **Normalize your data: **Follow the principles of database normalization to minimize data redundancy and improve data integrity. This includes creating appropriate tables, defining primary and foreign keys, and establishing relationships between entities. In App Studio, when querying data from one entity, you can retrieve related data from another entity by specifying a `join` clause on the query.
+ **Implement appropriate indexing: **Identify the most important queries and access patterns, and create appropriate indexes to optimize performance.
+ **Leverage AWS data services features: **Take advantage of the features offered by the AWS data service you choose, such as automated backups, multi-AZ deployments, and automatic software updates.
+ **Secure your data: **Implement robust security measures, such as IAM (AWS Identity and Access Management) policies, creation of database users with restricted permissions to tables and schemas, and enforce encryption at rest and in transit.
+ **Monitor and optimize performance: **Continuously monitor your database's performance and make adjustments as needed, such as scaling resources, optimizing queries, or tuning database configurations.
+ **Automate database management: **Utilize AWS services like Aurora Autoscaling, Performance Insights for Aurora, and AWS Database Migration Service to automate database management tasks and reduce operational overhead.
+ **Implement disaster recovery and backup strategies: **Ensure that you have a well-defined backup and recovery plan, leveraging features like Aurora Automated Backups, point-in-time recovery, and cross-region replica configurations.
+ **Follow AWS best practices and documentation: **Stay up-to-date with the latest AWS best practices, guidelines, and documentation for your chosen data service to ensure that your data model and implementation are aligned with AWS recommendations.

For more detailed guidance from each AWS data service, see the following topics:
+ [Best practices with Amazon Aurora](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.BestPractices.html)
+ [Best practices with Amazon Aurora MySQL](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.BestPractices.html)
+ [Amazon Redshift query performance tuning](https://docs.aws.amazon.com/redshift/latest/dg/c-optimizing-query-performance.html)
+ [Best practices for querying and scanning data in Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-query-scan.html)

# Creating an entity in an App Studio app
<a name="data-entities-create"></a>

There are four methods for creating an entity in an App Studio app. The following list contains each method, its benefits, and a link to the instructions for using that method to create and then configure the entity.
+ [Creating an entity from an existing data source](#data-entities-create-existing-data-source): Automatically create an entity and its fields from an existing data source table and map the fields to the data source table columns. This option is preferable if you have an existing data source that you want to use in your App Studio app.
+ [Creating an entity with an App Studio managed data source](#data-entities-create-managed-data-source): Create an entity and a DynamoDB table that App Studio manages for you. The DynamoDB table is automatically updated as you update your entity. With this option, you don't have to manually create, manage, or connect a third-party data source, or designate mapping from entity fields to table columns. All of your app's data modeling and configuration is done in App Studio. This option is preferable if you don't want to manage your own data sources and a DynamoDB table and its functionality is sufficient for your app.
+ [Creating an empty entity](#data-entities-create-empty): Create an empty entity entirely from scratch. This option is preferable if you don't have any existing data sources or connectors created by an admin, and you want to flexibly design your app's data model without being constrained by external data sources. You can connect the entity to a data source after creation.
+ [Creating an entity with AI](#data-entities-create-with-ai): Generate an entity, fields, data actions, and sample data based on the specified entity name. This option is preferable if you have an idea of the data model for your app, but you want help translating it into an entity.

## Creating an entity from an existing data source
<a name="data-entities-create-existing-data-source"></a>

Use a table from a data source to automatically create an entity and its fields, and map the entity fields to the columns of the table. This option is preferable if you have an existing data source that you want to use in your App Studio app.

1. If necessary, navigate to your application.

1. Choose the **Data** tab at the top of the canvas.

1. If there are no entities in your app, choose **\$1 Create entity**. Otherwise, in the left-side **Entities** menu, choose **\$1 Add**.

1. Select **Use a table from an existing data source**.

1. In **Connector**, select the connector that contains the table you want to use to create your entity.

1. In **Table**, choose the table you want to use to create your entity.

1. Select the **Create data actions** checkbox to create data actions.

1. Choose **Create entity**. Your entity is now created, and you can see it in the left-hand **Entities** panel.

1. Configure your new entity by following the procedures in [Configuring or editing an entity in an App Studio app](data-entities-edit.md). Note that because your entity was created with an existing data source, some properties or resources have already been created, such as fields, the connected data source, and field mapping. Also, your entity will contain data actions if you selected the **Create data actions** checkbox during creation.

## Creating an entity with an App Studio managed data source
<a name="data-entities-create-managed-data-source"></a>

Create a managed entity and corresponding DynamoDB table that is managed by App Studio. While the DynamoDB table exists in the associated AWS account, when changes are made to the entity in the App Studio app, the DynamoDB table is updated automatically. With this option, you don't have to manually create, manage, or connect a third-party data source, or designate mapping from entity fields to table columns. This option is preferable if you don't want to manage your own data sources and a DynamoDB table and its functionality is sufficient for your app. For more information about managed entities, see [Managed data entities in AWS App Studio](managed-data-entities.md).

You can use the same managed entities in multiple applications. For instructions, see [Creating an entity from an existing data source](#data-entities-create-existing-data-source).

1. If necessary, navigate to your application.

1. Choose the **Data** tab at the top of the canvas.

1. If there are no entities in your app, choose **\$1 Create entity**. Otherwise, in the left-side **Entities** menu, choose **\$1 Add**.

1. Select **Create App Studio managed entity**.

1. In **Entity name**, provide a name for your entity.

1. In **Primary key**, provide a name for the primary key of your entity. The primary key is the unique identifier of the entity and cannot be changed after the entity is created.

1. In **Primary key data type**, select the data type of primary key of your entity. The data type cannot be changed after the entity is created.

1. Choose **Create entity**. Your entity is now created, and you can see it in the left-hand **Entities** panel.

1. Configure your new entity by following the procedures in [Configuring or editing an entity in an App Studio app](data-entities-edit.md). Note that because your entity was created with managed data, some properties or resources have already been created, such as the primary key field, and the connected data source.

## Creating an empty entity
<a name="data-entities-create-empty"></a>

Create an empty entity entirely from scratch. This option is preferable if you don't have any existing data sources or connectors created by an admin. Creating an empty entity offers flexibility, as you can design your entity within your App Studio app without being constrained by external data sources. After you design your app's data model, and configure the entity accordingly, you can still connect it to an external data source later.

1. If necessary, navigate to your application.

1. Choose the **Data** tab at the top of the canvas.

1. If there are no entities in your app, choose **\$1 Create entity**. Otherwise, in the left-side **Entities** menu, choose **\$1 Add**.

1. Select **Create an entity**.

1. Choose **Create entity**. Your entity is now created, and you can see it in the left-hand **Entities** panel.

1. Configure your new entity by following the procedures in [Configuring or editing an entity in an App Studio app](data-entities-edit.md).

## Creating an entity with AI
<a name="data-entities-create-with-ai"></a>

Generate an entity, fields, data actions, and sample data based on the specified entity name. This option is preferable if you have an idea of the data model for your app, but you want help translating it into an entity.

1. If necessary, navigate to your application.

1. Choose the **Data** tab at the top of the canvas.

1. If there are no entities in your app, choose **\$1 Create entity**. Otherwise, in the left-side **Entities** menu, choose **\$1 Add**.

1. Select **Create an entity with AI**.

1. In **Entity name**, provide a name for your entity. This name is used to generate the fields, data actions, and sample data of your entity.

1. Select the **Create data actions** checkbox to create data actions.

1. Choose **Generate an entity**. Your entity is now created, and you can see it in the left-hand **Entities** panel.

1. Configure your new entity by following the procedures in [Configuring or editing an entity in an App Studio app](data-entities-edit.md). Note that because your entity was created with AI, your entity will already contain generated fields. Also, your entity will contain data actions if you selected the **Create data actions** checkbox during creation.

# Configuring or editing an entity in an App Studio app
<a name="data-entities-edit"></a>

Use the following topics to configure an entity in an App Studio application.

**Topics**
+ [Editing the entity name](data-entities-edit-name.md)
+ [Adding, editing, or deleting entity fields](data-entities-edit-fields.md)
+ [Creating, editing, or deleting data actions](data-entities-edit-data-actions.md)
+ [Adding or deleting sample data](data-entities-edit-sample-data.md)
+ [Add or edit connected data source and map fields](data-entities-edit-connection.md)

# Editing the entity name
<a name="data-entities-edit-name"></a>

1. If necessary, navigate to the entity you want to edit.

1. In the **Configuration** tab, in **Entity name**, update the entity name and choose outside of the text box to save your changes.

# Adding, editing, or deleting entity fields
<a name="data-entities-edit-fields"></a>

**Tip**  
You can press CTRL\$1Z to undo the most recent change to your entity.

1. If necessary, navigate to the entity you want to edit.

1. In the **Configuration** tab, in **Fields**, you view a table of your entity's fields. Entity fields have the following columns:
   + **Display name:** The display name is similar to a table header or form field and is viewable by application users. It can contain spaces and special characters but must be unique within an entity.
   + **System name:** The system name is a unique identifier used in code to reference a field. When mapping to a column in an Amazon Redshift table, it must match the Amazon Redshift table column name.
   + **Data type:** The type of data that will be stored within this field, such as `Integer`, `Boolean`, or `String`.

1. To add fields:

   1. To use AI to generate fields based on entity name and connected data source, choose **Generate more fields**.

   1. To add a single field, choose **\$1 Add field**.

1. To edit a field:

   1. To edit the display name, enter the desired value in the **Display name** text box. If the system name of the field hasn't been edited, it will be updated to the new value of the display name.

   1. To edit the system name, enter the desired value in the **System name** text box.

   1. To edit the data type, choose the **Data type** dropdown menu and select the desired type from the list.

   1. To edit the field's properties, choose the gear icon of the field. The following list details the field properties:
      + **Required**: Enable this option if the field is required by your data source.
      + **Primary key**: Enable this option if the field is mapped to a primary key in your data source.
      + **Unique**: Enable this option if the value of this field must be unique.
      + **Use data source default**: Enable this option if the value of the field is provided by the data source, such as using auto-increment, or an event timestamp.
      + **Data type options**: Fields of certain data types can be configured with data type options such as minimum or maximum values.

1. To delete a field, choose the trash icon of the field you want to delete.

# Creating, editing, or deleting data actions
<a name="data-entities-edit-data-actions"></a>

Data actions are used in applications to run actions on an entity's data, such as fetching all records, or fetching a record by ID. Data actions can be used to locate and return data matching specified conditions to be viewed in components such as tables or detail views.

**Contents**
+ [Creating data actions](#data-entities-data-action-add)
+ [Editing or configuring data actions](#data-entities-data-action-edit)
+ [Data action condition operators and examples](#data-entities-data-action-operators)
  + [Condition operator support by database](#data-entities-data-action-operators-support)
  + [Data action condition examples](#data-entities-data-action-operators-examples)
+ [Deleting data actions](#data-entities-data-action-delete)

## Creating data actions
<a name="data-entities-data-action-add"></a>

**Tip**  
You can press CTRL\$1Z to undo the most recent change to your entity.

1. If necessary, navigate to the entity for which you want to create data actions.

1. Choose the **Data actions** tab.

1. There are two methods for creating data actions:
   + (Recommended) To use AI to generate data actions for you, based on your entity name, fields, and connected data source, choose **Generate data actions**. The following actions will be generated:

     1. `getAll`: Retrieves all the records from an entity. This action is useful when you need to display a list of records or perform operations on multiple records at once.

     1. `getByID`: Retrieves a single record from an entity based on its unique identifier (ID or primary key). This action is useful when you need to display or perform operations on a specific record.
   + To add a single data action, choose **\$1 Add data action**.

1. To view or configure the new data action, see the following section, [Editing or configuring data actions](#data-entities-data-action-edit).

## Editing or configuring data actions
<a name="data-entities-data-action-edit"></a>

1. If necessary, navigate to the entity for which you want to create data actions.

1. Choose the **Data actions** tab.

1. In **Fields** configure the fields to be returned by the query. By default, all of the configured fields in the entity are selected.

   You can also add **Joins** to the data action by performing the following steps:

   1. Choose ** \$1 Add Join** to open a dialog box.

   1. In **Related entity**, select the entity you want to join with the current entity.

   1. In **Alias**, optionally enter a temporary alias name for the related entity.

   1. In **Join type**, select the desired join type.

   1. Define the join clause by selecting the fields from each entity.

   1. Choose **Add** to create the join.

   Once created, the join will be displayed in the **Joins** section, making additional fields available in the **Fields to Return** dropdown. You can add multiple joins, including chained joins across entities. You can also filter and sort by fields from joined entities.

   To delete a join, choose the trash icon next to it. This will remove any fields from that join and break any dependent joins or constraints using those fields.

1. In **Conditions**, add, edit, or remove rules that filter the output of the query. You can organize rules into groups, and you can chain together multiple rules with `AND` or `OR` statements. For more information about the operators you can use, see [Data action condition operators and examples](#data-entities-data-action-operators).

1. In **Sorting**, configure how the query results are sorted by choosing an attribute and choosing ascending or descending order. You can remove the sorting configuration by choosing the trash icon next to the sorting rule.

1. In **Transform results**, you can enter custom JavaScript to modify or format results before they are displayed or sent to automations.

1. In **Output preview**, view a preview table of the query output based on the configured fields, filters, sorting, and JavaScript.

## Data action condition operators and examples
<a name="data-entities-data-action-operators"></a>

You can use condition operators to compare a configured expression value with an entity column to return a subset of database objects. The operators that you can use depend on on the data type of the column, and the type of database that the entity is connected to, such as Amazon Redshift, Amazon Aurora, or Amazon DynamoDB.

The following condition operators can be used with all database services:
+ `=` and `!=`: Available for all data types (excluding primary key columns).
+ `<=`, `>=`, `<`, and `>=`: Available only to numerical columns.
+ `IS NULL` and `IS NOT NULL`: Used to match columns that have null or empty values. Null values are often interpreted differently in each database, however in App Studio, the `NULL` operator matches and returns records that have null values in the connected database table.

The following condition operators can only be used in entities that are connected to database services that support them:
+ `LIKE` and `NOT LIKE`(Redshift, Aurora): Used for performing pattern-based queries in the connected database. The `LIKE` operator provides flexibility in search functionality because it finds and returns records that fit the specified patterns. You define the patterns using wildcard characters that match any character or sequence of characters within the pattern. Each database management system has a unique set of wildcard characters, but the two most popular are `%` to represent any number of characters (including 0), and `_` to represent a single character.
+ `Contains` and `Not Contains` (DynamoDB): Used for performing a case-sensitive search to determine whether the given text is found within the column values. 
+ `Starts With` and `Not Starts With` (DynamoDB): Used for performing a case-sensitive search to determine whether the given text is found at the beginning of the column values. 

### Condition operator support by database
<a name="data-entities-data-action-operators-support"></a>

The following table shows which data action condition operators are supported by each database that can connect to App Studio.


|  | =, \$1=, <, >, <=, >= | LIKE, NOT LIKE | Contains, Not Contains | Starts With, Not Starts With | IS NULL, IS NOT NULL | 
| --- | --- | --- | --- | --- | --- | 
|  **DynamoDB**  |  Yes  |  No  |  Yes  |  Yes  |  Yes  | 
|  **Aurora**  |  Yes  |  Yes  |  No  |  No  |  Yes  | 
|  **Redshift**  |  Yes  |  Yes  |  No  |  No  |  Yes  | 

### Data action condition examples
<a name="data-entities-data-action-operators-examples"></a>

Consider the following database table, which includes multiple items with `name`, `city`, and `hireDate` fields.


| name | city | hireDate | 
| --- | --- | --- | 
|  Adam  |  Seattle  |  2025-03-01  | 
|  Adrienne  |  Boston  |  2025-03-05  | 
|  Bob  |  Albuquerque  |  2025-03-06  | 
|  Carlos  |  Chicago  |  2025-03-10  | 
|  Caroline  |  NULL  |  2025-03-12  | 
|  Rita  |  Miami  |  2025-03-15  | 

Now, consider creating data actions in App Studio that return the `name` field for items that match specified conditions. The following list contains condition examples and the values that the table returns for each. 

**Note**  
The examples are formatted as SQL examples– they may not appear as they do in App Studio, but are used to illustrate the behavior of the operators.
+ `WHERE name LIKE 'Adam'`: Returns `Adam`.
+ `WHERE name LIKE 'A%'`: Returns `Adam` and `Adrienne`.
+ `WHERE name NOT LIKE 'B_B'`: Returns `Adam`, `Adrienne`, `Carlos`, `Caroline`, and `Rita`.
+ `WHERE contains(name, 'ita')`: Returns `Rita`.
+ `WHERE begins_with(name, 'Car')`: Returns `Carlos` and `Caroline`.
+ `WHERE city IS NULL`: Returns `Caroline`.
+ `WHERE hireDate < "2025-03-06"`: Returns `Adam` and `Adrienne`.
+ `WHERE hireDate >= DateTime.now().toISODate()`: Note that `DateTime.now().toISODate()` returns the current date. In a scenario where the current date is 2025-03-10, the expression returns `Carlos`, `Caroline`, and `Rita`.

**Tip**  
For more information about comparing dates and times in expressions, see [Date and time](expressions.md#expressions-date-time).

## Deleting data actions
<a name="data-entities-data-action-delete"></a>

Use the following procedure to delete data actions from an App Studio entity.

1. If necessary, navigate to the entity for which you want to delete data actions.

1. Choose the **Data actions** tab.

1. For each data action you want to delete, choose the dropdown menu next to **Edit** and choose **Delete**.

1. Choose **Confirm** in the dialog box.

# Adding or deleting sample data
<a name="data-entities-edit-sample-data"></a>

You can add sample data to entities in an App Studio application. Because application's don't communicate with external services until they are published, sample data can be used to test your application and entity in preview environments.

1. If necessary, navigate to the entity you want to edit.

1. Choose the **Sample data** tab.

1. To generate sample data, choose **Generate more sample data**.

1. To delete sample data, select the checkboxes of the data you want to delete, and press the Delete or Backspace key. Choose **Save** to save the changes.

# Add or edit connected data source and map fields
<a name="data-entities-edit-connection"></a>

**Tip**  
You can press CTRL\$1Z to undo the most recent change to your entity.

1. If necessary, navigate to the entity you want to edit.

1. Choose the **Connection** tab to view or manage the connection between the entity and a data source table where data is stored when your application is published. Once a data source table is connected, you can map the entity fields to the columns of the table.

1. In **Connector**, choose the connector that contains a connection to the desired data source table. For more information about connectors, see [Connect App Studio to other services with connectors](connectors.md).

1. In **Table**, choose the table you want to use as a data source for the entity.

1. The table shows the fields of entity, and the data source column they are mapped to. Choose **Auto map** to automatically map your entity fields with your data source columns. You can also map fields manually in the table by choosing the data source column in the dropdown for each entity field.

# Deleting an entity
<a name="data-entities-delete"></a>

Use the following procedure to delete an entity from an App Studio application.

**Note**  
Deleting an entity from an App Studio app does not delete the connected data source table, including the corresponding DynamoDB table of managed entities. The data source tables will remain in the associated AWS account and will need to be deleted from the corresponding service if desired.

**To delete an entity**

1. If necessary, navigate to your application.

1. Choose the **Data** tab.

1. In the left-hand **Entities** menu, choose the ellipses menu next to the entity you want to delete and choose **Delete**.

1. Review the information in the dialog box, enter **confirm** and choose **Delete** to delete the entity.

# Managed data entities in AWS App Studio
<a name="managed-data-entities"></a>

Typically, you configure an entity in App Studio with a connection to an external database table, and you must create and map each entity field with a column in the connected database table. When you make a change to the data model, both the external database table and the entity must be updated, and the changed fields must be remapped. While this method is flexible and enables the use of different types of data sources, it takes more up-front planning and ongoing maintenance.

A *managed entity* is a type of entity for which App Studio manages the entire data storage and configuration process for you. When you create a managed entity, a corresponding DynamoDB table is created in the associated AWS account. This ensures secure and transparent data management within AWS. With a managed entity, you configure the entity's schema in App Studio, and the corresponding DynamoDB table is automatically updated as well.

## Using managed entities in multiple applications
<a name="managed-data-entities-other-applications"></a>

Once you create a managed entity in an App Studio app, that entity can be used in other App Studio apps. This is helpful for configuring data storage for apps with identical data models and schemas by providing a single underlying resource to maintain.

When using a managed entity in multiple applications, all schema updates to the corresponding DynamoDB table must be made using the original application in which the managed entity was created. Any schema changes made to the entity in other applications will not update the corresponding DynamoDB table.

## Managed entity limitations
<a name="managed-data-entities-limitations"></a>

**Primary key update restrictions**: You cannot change the entity's primary key name or type after it is created, as this is a destructive change in DynamoDB, and would result in loss of existing data.

**Renaming columns**: When you rename a column in DynamoDB, you actually create a new column while the original column remains with original data. The original data is not automatically copied to the new column or deleted from the original column. You can rename managed entity fields, known as the *system name*, but you will lose access to the original column and its data. There is no restriction with renaming the display name.

**Changing data type**: Though DynamoDB allows flexibility to modify column data types after table creation, such changes can severely impact existing data as well as query logic and accuracy. Data type changes require transforming all existing data to conform to the new format, which is complex for large, active tables. Additionally, data actions may return unexpected results until data migration is complete. You can switch data types of fields, but the existing data will not be migrated to the new data type.

**Sorting Column**: DynamoDB enables sorted data retrieval through Sort Keys. Sort Keys must be defined as part of composite Primary Keys along with the Partition Key. Limitations include mandatory Sort Key, sorting confined within one partition, and no global sorting across partitions. Careful data modeling of Sort Keys is required to avoid hot partitions. We will not be supporting Sorting for Preview milestone.

**Joins**: Joins are not supported in DynamoDB. Tables are denormalized by design to avoid expensive join operations. To model one-to-many relationships, the child table contains an attribute referencing the parent table's primary key. Multi-table data queries involve looking up items from the parent table to retrieve details. We will not be supporting native Joins for Managed entities as part of the Preview milestone. As a workaround, we will introduce an automation step that can perform a data merge of 2 entities. This will be very similar to a one level look-up. We will not be supporting Sorting for Preview milestone.

**Env Stage**: We will allow publishing to test but use the same managed store across both environments

# Page and automation parameters
<a name="paramters"></a>

Parameters are a powerful feature in AWS App Studio that are used to pass dynamic values between different components, pages, and automations within your application. Using parameters, you can make flexible and context-aware experiences, making your applications more responsive and personalized. This article covers two types of parameters: page parameters and automation parameters.

**Topics**
+ [Page parameters](parameters-page.md)
+ [Automation parameters](parameters-automation.md)

# Page parameters
<a name="parameters-page"></a>

Page parameters are a way to send information between pages and are often used when navigating from one page to another within an App Studio app to maintain context or pass data. Page parameters typically consist of a name and a value.

## Page parameter use cases
<a name="parameters-pages-use-cases"></a>

Page parameters are used for passing data between different pages and components within your App Studio applications. They are particularly helpful for the following use cases:

1. **Searching and filtering**: When users search on your app's homepage, the search terms can be passed as parameters to the results page, allowing it to display only the relevant filtered items. For example, if a user searches for *noise-cancelling headphones*, the parameter with the value *noise-cancelling headphones* can be passed to the product listing page.

1. **Viewing item details**: If a user clicks on a listing, such as a product, the unique identifier of that item can be passed as a parameter to the details page. This allows the details page to display all the information about the specific item. For example, when a user clicks on a headphone product, the product's unique ID is passed as a parameter to the product details page.

1. **Passing user context in page navigation**: As users navigate between pages, parameters can pass along important context, such as the user's location, preferred product categories, shopping cart contents, and other settings. For example, as a user browses through different product categories on your app, their location and preferred categories are retained as parameters, providing a personalized and consistent experience.

1. **Deep links**: Use page parameters to share or bookmark a link to a specific page within the app.

1. **Data actions**: You can create data actions that accept parameter values to filter and query your data sources based on the passed parameters. For example, on the product listing page, you can create a data action that accepts `category` parameters to fetch the relevant products.

## Page parameter security considerations
<a name="parameters-pages-security"></a>

While page parameters provide a powerful way to pass data between pages, you must use them with caution, as they can potentially expose sensitive information if not used properly. Here is an important security considerations to keep in mind:

1. **Avoid exposing sensitive data in URLs**

   1. **Risk**: URLs, including data action parameters, are often visible in server logs, browser history, and other places. As such, it's essential to avoid exposing sensitive data, such as user credentials, personal identifiable information (PII), or any other confidential data, in page parameter values.

   1. **Mitigation**: Consider using identifiers that can be securely mapped to the sensitive data. For example, instead of passing a user's name or email address as a parameter, you could pass a random unique identifier that can be used to fetch the user's name or email.

# Automation parameters
<a name="parameters-automation"></a>

Automation parameters are a powerful feature in App Studio that can be used to create flexible and reusable automations by passing dynamic values from various sources, such as the UI, other automations, or data actions. They act as placeholders that are replaced with actual values when the automation is run, allowing you to use the same automation with different inputs each time. 

Within an automation, parameters have unique names, and you can reference a parameter's value using the params variable followed by the parameter's name, for example, `{{params.customerId}}`.

This article provides an in-depth understanding of automation parameters, including their fundamental concepts, usage, and best practices.

## Automation parameter benefits
<a name="parameters-automation-benefits"></a>

Automation parameters provide several benefits, including the following list:

1. **Reusability**: By using parameters, you can create reusable automations that can be customized with different input values, allowing you to reuse the same automation logic with different inputs.

1. **Flexibility**: Instead of hard-coding values into an automation, you can define parameters and provide different values when needed, making your automations more dynamic and adaptable.

1. **Separation of concerns**: Parameters help separate the automation logic from the specific values used, promoting code organization and maintainability.

1. **Validation**: Each parameter has a data type, such as string, number, or boolean, which is validated at runtime. This ensures that requests with incorrect data types are rejected without the need for custom validation code.

1. **Optional and required parameters**: You can designate automation parameters as optional or required. Required parameters must be provided when running the automation, while optional parameters can have default values or be omitted. This flexibility allows you to create more versatile automations that can handle different scenarios based on the provided parameters.

## Scenarios and use cases
<a name="parameters-automation-scenarios"></a>

### Scenario: Retrieving product details
<a name="parameters-automation-scenario-product-details"></a>



Imagine you have an automation that retrieves product details from a database based on a product ID. This automation could have a parameter called `productId`.

The `productId` parameter acts as a placeholder that you can fill in with the actual product ID value when running the automation. Instead of hard-coding a specific product ID into the automation, you can define the `productId` parameter and pass in different product ID values each time you run the automation.

You could call this automation from a component's data source, passing the selected product's ID as the `productId` parameter using the double curly bracket syntax: `{{ui.productsTable.selectedRow.id}}`. This way, when a user selects a product from a table (`ui.productsTable`), the automation will retrieve the details for the selected product by passing the id of the selected row as the `productId` parameter.

Alternatively, you could invoke this automation from another automation that loops over a list of products and retrieves the details for each product by passing the product's id as the `productId` parameter. In this scenario, the `productId` parameter value would be dynamically provided from the `{{product.id}}` expression in each iteration of the loop.

By using the `productId` parameter and the double curly bracket syntax, you can make this automation more flexible and reusable. Instead of creating separate automations for each product, you can have a single automation that can retrieve details for any product by simply providing the appropriate product ID as the parameter value from different sources, such as UI components or other automations.

### Scenario: Handling optional parameters with fallback values
<a name="parameters-automation-scenario-optional-parameters"></a>

Let's consider a scenario where you have a "Task" entity with a required "Owner" column, but you want this field to be optional in the automation and provide a fallback value if the owner is not selected.

1. Create an automation with a parameter named `Owner` that maps to the `Owner` field of the `Task` entity.

1. Since the `Owner` field is required in the entity, the `Owner` parameter will synchronize with the required setting.

1. To make the `Owner` parameter optional in the automation, toggle the `required` setting off for this parameter.

1. In your automation logic, you can use an expression like `{{params.Owner || currentUser.userId}}`. This expression checks if the `Owner` parameter is provided. If it's not provided, it will fallback to the current user's ID as the owner.

1. This way, if the user doesn't select an owner in a form or component, the automation will automatically assign the current user as the owner for the task.

By toggling the `required` setting for the `Owner` parameter and using a fallback expression, you can decouple it from the entity field requirement, make it optional in the automation, and provide a default value when the parameter is not provided.

## Defining automation parameter types
<a name="parameters-automation-create"></a>

By using parameter types to specify data types and set requirements, you can control the inputs for your automations. This helps ensure your automations run reliably with the expected inputs.

### Synchronizing types from an entity
<a name="parameters-automation-synchronize-entity"></a>

Dynamically synchronizing parameter types and requirements from entity field definitions streamlines building automations that interact with entity data, ensuring that the parameter always reflects the latest entity field type and requirements.

The following procedure details general steps for synchronizing parameter types from an entity:

1. Create an entity with typed fields (e.g. Boolean, Number, etc.) and mark fields as needed.

1. Create a new automation.

1. Add parameters to the automation, and when choosing the **Type**, choose the entity field you want to sync with. The data type and required setting will automatically synchronize from the mapped entity field

1. If needed, you can override the "required" setting by toggling it on/off for each parameter. This means the required status will not be kept in sync with the entity field, but otherwise, it will remain synchronized.

### Manually defining types
<a name="parameters-automation-custom-types"></a>

You can also define parameter types manually without synchronizing from an entity

By defining custom parameter types, you can create automations that accept specific input types and handle optional or required parameters as needed, without relying on entity field mappings.

1. Create an entity with typed fields (e.g. Boolean, Number, etc.) and mark fields as needed.

1. Create a new automation.

1. Add parameters to the automation, and when choosing the **Type**, choose desired type.

## Configuring dynamic values to be passed to automation parameters
<a name="parameters-automation-pass-values"></a>

Once you've defined parameters for an automation, you can pass values to them when invoking the automation. You can pass parameter values in two ways:

1. **Component triggers**: If you're invoking the automation from a component trigger, such as a button click, you can use JavaScript expressions to pass values from the component context. For example, if you have a text input field named `emailInput`, you can pass its value to the email parameter with the following expression: `ui.emailInput.value`.

1. **Other automations**: If you're invoking the automation from another automation, you can use JavaScript expressions to pass values from the automation context. For example, you can pass the value of another parameter or the result of a previous action step.

## Type safety
<a name="parameters-automation-type-safety"></a>

By defining parameters with specific data types, such as String, Number, or Boolean, you can ensure that the values passed into your automation are of the expected type.

**Note**  
In App Studio, date(s) are ISO string dates, and those will be validated too.

This type safety helps prevent type mismatches, which can lead to errors or unexpected behavior in your automation logic. For example, if you define a parameter as a `Number`, you can be confident that any value passed to that parameter will be a number, and you won't have to perform additional type checks or conversions within your automation.

## Validation
<a name="parameters-automation-validation"></a>

You can add validation rules to your parameters, ensuring that the values passed into your automation meet certain criteria.

While App Studio does not provide built-in validation settings for parameters, you can implement custom validations by adding a JavaScript action to your automation that throws an error if specific constraints are violated.

For entity fields, a subset of validation rules, such as minimum/maximum values, are supported. However, those are not validated at the automation level, only at the data layer, when running Create/Update/Delete Record actions.

## Best practices for automation parameters
<a name="parameters-automation-best-practices"></a>

To ensure that your automation parameters are well-designed, maintainable, and easy to use, follow these best practices:

1. **Use descriptive parameter names**: Choose parameter names that clearly describe the purpose or context of the parameter.

1. **Provide parameter descriptions**: Take advantage of the **Description** field when defining parameters to explain their purpose, constraints, and expectations. These descriptions will be surfaced in the JSDoc comments when referencing the parameter, as well as in any user interfaces where users need to provide values for the parameters when invoking the automation.

1. **Use appropriate data types**: Carefully consider the data type of each parameter based on the expected input values, for example: String, Number, Boolean, Object.

1. **Validate parameter values**: Implement appropriate validation checks within your automation to ensure that parameter values meet specific requirements before proceeding with further actions.

1. **Use fallback or default values**: While App Studio does not currently support setting default values for parameters, you can implement fallback or default values when consuming the parameters in your automation logic. For example, you can use an expression like `{{ params.param1 || "default value" }}` to provide a default value if the `param1` parameter is not provided or has a false value.

1. **Maintain parameter consistency**: If you have multiple automations that require similar parameters, try to maintain consistency in parameter names and data types across those automations.

1. **Document parameter usage**: Maintain clear documentation for your automations, including descriptions of each parameter, its purpose, expected values, and any relevant examples or edge cases.

1. **Review and refactor frequently**: Periodically review your automations and their parameters, refactoring or consolidating parameters as needed to improve clarity, maintainability, and reusability.

1. **Limit the number of parameters**: While parameters provide flexibility, too many parameters can make an automation complex and difficult to use. Aim to strike a balance between flexibility and simplicity by limiting the number of parameters to only what is necessary.

1. **Consider parameter grouping**: If you find yourself defining multiple related parameters, consider grouping them into a single *Object* parameter.

1. **Separate concerns**: Avoid using a single parameter for multiple purposes or combining unrelated values into a single parameter. Each parameter should represent a distinct concern or piece of data.

1. **Use parameter aliases**: If you have parameters with long or complex names, consider using aliases or shorthand versions within the automation logic for better readability and maintainability.

By following these best practices, you can ensure that your automation parameters are well-designed, maintainable, and easy to use, ultimately improving the overall quality and efficiency of your automations.

# Using JavaScript to write expressions in App Studio
<a name="expressions"></a>

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.

**Important**  
App Studio does not support using third-party or custom JavaScript libraries.

## Basic syntax
<a name="expressions-basic-syntax"></a>

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\$1".
+ `{{ Math.max(5, 10) }}` will evaluate to 10.
+ `{{ Math.random() * 10 }}` returns a random number (with decimals) between [0-10).

## Interpolation
<a name="expressions-interpolation"></a>

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
<a name="expressions-concatenation"></a>

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. For example, if `currentRow.FirstName` is `John`, and `currentRow.LastName` is `Doe`, then the expression would resolve to `John Doe`.

## Date and time
<a name="expressions-date-time"></a>

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.

### Date and time comparison
<a name="expressions-date-time-comparison"></a>

Use operators such as `=`, `>`, `<`, `>=`, or `<=` to compare date or time values. For example:
+ `{{ui.timeInput.value > "10:00 AM"}}`: Checks if the time is after 10:00 AM.
+ `{{ui.timeInput.value <= "5:00 PM"}}`: Checks if the time is at or before 5:00 PM.
+ `{{ui.timeInput.value > DateTime.now().toISOTime()}}`: Checks if the time is after the current time.
+ `{{ui.dateInput.value > DateTime.now().toISODate()}}`: Checks if the date is before the current date.
+ `{{ DateTime.fromISO(ui.dateInput.value).diff(DateTime.now(), "days").days >= 5 }}`: Checks if the date is at least 5 days from the current date.

## Code blocks
<a name="expressions-code-block"></a>

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
<a name="expressions-global-variables-functions"></a>

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.

## Referencing or updating UI component values
<a name="expressions-UI-component-values"></a>

You can use expressions in components and automation actions to both reference and update UI component values. By programmatically referencing and updating component values, you can create dynamic and interactive user interfaces that respond to user input and data changes.

### Referencing UI component values
<a name="expressions-UI-component-values-referencing"></a>

You can create interactive and data-driven applications by implementing dynamic behavior by accessing values from UI components.

You can access values and properties of UI components on the same page by using the `ui` namespace in expressions. By referencing a component's name, you can retrieve its value or perform operations based on its state.

**Note**  
The `ui` namespace will only show components on the current page, as components are scoped to their respective pages.

The basic syntax for referring to components in an App Studio app is: `{{ui.componentName}}`.

The following list contains examples for using the `ui` namespace to access UI component values:
+ `{{ui.textInputName.value}}`: Represents the value of a text input component named *textInputName*.
+ `{{ui.formName.isValid}}`: Check if all fields in the form named *formName* are valid based on your provided validation criteria.
+ `{{ui.tableName.currentRow.columnName}}`: Represents the value of a specific column in the current row of a table component named *tableName*.
+ `{{ui.tableName.selectedRowData.fieldName}}`: Represents the value of the specified field from the selected row in a table component named *tableName*. You can then append a field name such as `ID` (`{{ui.tableName.selectedRowData.ID}}`) to reference the value of that field from the selected row.

The following list contains more specific examples of referencing component values:
+ `{{ui.inputText1.value.trim().length > 0}}`: Check if the value of the *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.multiSelect1.value.join(", ")}}`: For a multi-select component named *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.multiSelect1.value.includes("option1")}}`: This expression checks if the value *option1* is included in the array of selected options for the *multiSelect1* component. It returns true if *option1* is selected, and false otherwise. This can be useful for conditionally rendering components or taking actions based on specific option selections.
+ `{{ui.s3Upload1.files.length > 0}}`: For an Amazon S3 file upload component named *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.s3Upload1.files.filter(file => file.type === "image/png").length}}`: This expression filters the list of uploaded files in the *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.

### Updating UI component values
<a name="expressions-UI-component-values-updating"></a>

To update or manipulate the value of a component, use the `RunComponentAction` within an automation. Here's an example of the syntax you can use to update the value of a text input component named *myInput* using the `RunComponentAction` action:

```
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*.

## Working with table data
<a name="expressions-table-data"></a>

You can access table data and values to perform operations. You can use the following expressions to access table data:
+ `currentRow`: Used to access table data from the current row within the table. For example, setting a table action's name, sending a value from the row to an automation that is started from an action, or using values from existing columns in a table to create a new column.
+ `ui.tableName.selectedRow` and `ui.tableName.selectedRowData` are both used to access table data from other components on the page. For example, setting a button's name outside of the table based on the selected row. The values returned are the same, but the differences between `selectedRow` and `selectedRowData` are as follows:
  + `selectedRow`: This namespace includes the name shown in the column header for each field. You should use `selectedRow` when referencing a value from a visible column in the table. For example, if you have a custom or computed column in your table that doesn't exist as a field in the entity.
  + `selectedRowData`: This namespace includes the fields in the entity used as a source for the table. You should use `selectedRowData` to reference a value from the entity that isn't visible in the table, but is useful for other components or automations in your app.

The following list contains examples of accessing table data in expressions:
+ `{{ui.tableName.selectedRow.columnNameWithNoSpace}}`: Returns the value of the *columnNameWithNoSpace* column from the selected row in the table.
+ `{{ui.tableName.selectedRow.['Column Name With Space']}}`: Returns the value of the *Column Name With Space* column from the selected row in the table.
+ `{{ui.tableName.selectedRowData.fieldName}}`: Returns the value of the *fieldName* entity field from the selected row in the table.
+ `{{ui.tableName.selectedRows[0].columnMappingName}}`: Reference the selected row's column name from other components or expressions on the same page.
+ `{{currentRow.firstName + ' ' + currentRow.lastNamecolumnMapping}}`: Concatenate values from multiple columns to create a new column in a table.
+ `{{ { "Blocked": "🔴", "Delayed": "🟡", "On track": "🟢" }[currentRow.statuscolumnMapping] + " " + currentRow.statuscolumnMapping}}`: Customize the display value of a field within a table based on the stored status value.
+ `{{currentRow.colName}}`, `{{currentRow["First Name"]}}`, `{{currentRow}}`, or `{{ui.tableName.selectedRows[0]}}`: Pass the referenced row's context within a row action.

## Accessing automations
<a name="expressions-automations"></a>

You can use automations to run server-side logic and operations in App Studio. Within automation actions, you can use expressions to process data, generate dynamic values, and incorporate results from previous actions.

### Accessing automation parameters
<a name="expressions-automations-parameters"></a>

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.parameterName}}`: Reference a value passed into the automation from a UI component or other source. For example, `{{params.ID}}` would reference a parameter named *ID*.

#### Manipulating automation parameters
<a name="expressions-automations-parameters-manipulate"></a>

You can use JavaScript to manipulate automation parameters. See the following examples:
+ `{{params.firstName}} {{params.lastName}}`: Concatenate values passed as parameters.
+ `{{params.numberParam1 + params.numberParam2}}`: Add two number parameters.
+ `{{params.valueProvided?.length > 0 ? params.valueProvided : 'Default'}}`: 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.
+ `{{params.rootCause || "No root cause provided"}}`: If the `params.rootCause` parameter is false (null, undefined, or an empty string), use the provided default value.
+ `{{Math.min(params.numberOfProducts, 100)}}`: Restrict the value of a parameter to a maximum value (in this case, `100`).
+ `{{ DateTime.fromISO(params.startDate).plus({ days: 7 }).toISO() }}`: If the `params.startDate` parameter is `"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
<a name="expressions-automations-results"></a>

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:

1. You can only access results of previous automation steps within the same automation.

1. If you have actions named *action1* and *action2* in that order, *action1* cannot reference any results, and *action2* can only access `results.action1`.

1. 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 a `Run If` condition like `results.myInvokeAutomation1.fileType === "pdf"` to navigate to a page with a PDF viewer if the automation indicates the file is a PDF.

The following list contains the syntax for accessing automation results from a previous action using the `results` namespace.
+ `{{results.stepName.data}}`: Retrieve the data array from an automation step named *stepName*.
+ `{{results.stepName.output}}`: Retrieve the output of an automation step named *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.data`.
+ For an API call action, you may access the response body using `results.stepName.body`.
+ For 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.getDataStep.data.filter(row => row.status === "pending").length}}`: Assuming the *getDataStep* is an `Invoke 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 to `pending`, and returns the length (count) of the filtered array. This can be useful for querying or processing data based on specific conditions.
+ `{{params.email.split("@")[0]}}`: If the `params.email` 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.
+ `{{new Date(params.timestamp * 1000)}}`: This expression takes a Unix timestamp parameter (`params.timestamp`) 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 the `Date` constructor. This can be useful for working with date and time values in automations.
+ `{{results.stepName.Body}}`: For an `Amazon S3 GetObject` automation action named *stepName*, 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.

# Data dependencies and timing considerations
<a name="data-dependencies-timing-considerations"></a>

When building complex applications in App Studio, it's crucial to understand and manage data dependencies between different data components, such as forms, detail views, and automation-powered components. Data components and automations may not complete their data retrieval or execution at the same time, which can lead to timing issues, errors, and unexpected behavior. By being aware of potential timing issues and following best practices, you can create more reliable and consistent user experiences in your App Studio applications.

Some potential issues are as follows:

1. **Render timing conflicts:** Data components may render in an order that doesn't align with their data dependencies, potentially causing visual inconsistencies or errors.

1. **Automation run timing:** Automation tasks may complete before components have fully loaded, leading to runtime execution errors.

1. **Component crashes:** Components powered by automations may crash on invalid responses or when the automation hasn't finished running.

## Example: Order details and customer information
<a name="data-dependencies-timing-considerations-example"></a>

This example demonstrates how dependencies between data components can lead to timing issues and potential errors in data display.

Consider an application with the following two data components on the same page:
+ A Detail component (`orderDetails`) that fetches order data.
+ A Detail component (`customerDetails`) that displays customer details related to the order.

In this application, there are two fields in the `orderDetails` detail component, configured with the following values:

```
// 2 text fields within the orderDetails detail component

// Info from orderDetails Component
{{ui.orderDetails.data[0].name}} 

// Info from customerDetails component
{{ui.customerDetails.data[0].name}} // Problematic reference
```

In this example, the `orderDetails` component is attempting to display the customer name by referencing data from the `customerDetails` component. This is problematic, because the `orderDetails` component may render before the `customerDetails` component has fetched its data. If the `customerDetails` component data fetch is delayed or fails, the `orderDetails` component will display incomplete or incorrect information. 

## Data dependency and timing best practices
<a name="data-dependencies-timing-considerations-example"></a>

Use the following best practices to mitigate data dependency and timing issues in your App Studio app:

1. **Use conditional rendering:** Only render components or display data when you've confirmed it's available. Use conditional statements to check for data presence before displaying it. The following snippet shows an example conditional statement:

   ```
   {{ui.someComponent.data ? ui.someComponent.data.fieldName : "Loading..."}}
   ```

1. **Manage child component visibility:** For components like Stepflow, Form, or Detail that render children before their data is loaded, manually set the visibility of child components. The following snippet shows an example of setting visibility based on parent component data availability:

   ```
   {{ui.parentComponent.data ? true : false}}
   ```

1. **Use join queries:** When possible, use join queries to fetch related data in a single query. This reduces the number of separate data fetches and minimizes timing issues between data components.

1. **Implement error handing in automations:** Implement robust error handling in your automations to gracefully manage scenarios where expected data is not available or invalid responses are received.

1. **Use optional chaining:** When accessing nested properties, use optional chaining to prevent errors if a parent property is undefined. The following snippet shows an example of optional chaining:

   ```
   {{ui.component.data?.[0]?.fieldSystemName}}
   ```

# Building an app with multiple users
<a name="builder-collaboration"></a>

Multiple users can work on a single App Studio app, however only one user can edit an app at one time. See the following sections to information about inviting other users to edit an app, and the behavior when multiple users try to edit an app at the same time.

## Invite builders to edit an app
<a name="builder-collaborate-invite"></a>

Use the following instructions to invite other builders to edit an App Studio app.

**To invite other builders to edit an app**

1. If necessary, navigate to the application studio of your application.

1. Choose **Share**.

1. In the **Development** tab, use the text box to search for and select groups or individual users that you want to invite to edit the app.

1. For each user or group, choose the dropdown and select the permissions to give to that user or group.
   + **Co-owner**: Co-owners have the same permissions as app owners.
   + **Edit only**: Users with the **Edit only** role have the same permissions as owners and co-owners, except for the following:
     + They cannot invite other users to edit the app.
     + They cannot publish the app to the Testing or Production environments.
     + They cannot add data sources to the app.
     + They cannot delete or duplicate the app.

## Attempting to edit an app that is being edited by another user
<a name="builder-collaborate-behavior"></a>

A single App Studio app can only be edited by one user at a time. See the following example to understand what happens when multiple users try to edit an app at the same time.

In this example, `User A` is currently editing an app, and has shared it with `User B`. `User B` then attempts to edit the app that is being edited by `User A`.

When `User B` tries to edit the app, a dialog box will appear informing them that `User A` is currently editing the app, and that continuing will kick `User A` out of the application studio, and all changes will be saved. `User B` can choose to cancel and let `User A` continue, or continue and enter the application studio to edit the app. In this example, they choose to edit the app.

When `User B` chooses to edit the app, `User A` receives a notification that `User B` has started editing the app, and their session has ended. Note that if `User A` had the app open in an inactive browser tab, they may not receive the notification. In this case, if they try to come back to the app and try to make an edit, they will receive an error message and be guided to refresh the page, which will return them to the list of applications.

# Viewing or updating your app's content security settings
<a name="app-content-security-settings-csp"></a>

Every application in App Studio has content security settings that can be used to restrict external media or resources such as images, iFrames, and PDFs from being loaded, or only permitted from specified domains or URLs (including Amazon S3 buckets). You can also specify the domains that your app can upload objects to Amazon S3 to.

The default content security settings for all apps is to block loading all media from external sources, including Amazon S3 buckets, and block uploading objects to Amazon S3. Therefore, in order to load images, iFrames, PDFs, or similar media, you must edit the settings to allow the sources of the media. Also, to allow uploading objects to Amazon S3, you must edit the settings to allow the domains that can be uploaded to.

**Note**  
The content security settings are used to configure Content Security Policy (CSP) headers in your application. CSP is a security standard that helps to secure your app from cross-site scripting (XSS), clickjacking, and other code injection attacks. For more information about CSP, see [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) in the MDN Web Docs.

**To update your app's content security settings**

1. If necessary, navigate to the application studio of your application by choosing to edit it from the application list.

1. Choose **App settings**.

1. Choose the **Content Security Settings** tab to view the following settings:
   + **Frame source**: Used to manage the domains that your app can load frames and iframes (such as interactive content or PDFs) from. This setting affects the following components or app resources:
     + iFrame embed component
     + PDF viewer component
   + **Image source**: Used to manage the domains that your app can load images from. This setting affects the following components or app resources:
     + App logo and banner
     + Image viewer component
   + **Connect source**: Used to manage the domains that your app can upload Amazon S3 objects to.

1. For each setting, choose the desired setting from the dropdown:
   + **Block all frames/images/connections**: Do not allow any media (images, frames, PDFs) to load, or any objects to be uploaded to Amazon S3.
   + **Allow all frames/images/connections**: Allow all media (images, frames, PDFs) from all domains to load, or allow uploading of objects to Amazon S3 for all domains.
   + **Allow specific domains**: Allow loading media from or uploading media to specified domains. Domains or URLs are specified as a space-separated list of expressions, where wildcards (`*`) can be used for subdomains, host address, or port number to indicate that all legal values of each are valid. Specifying `http` also matches `https`. The following list contains examples of valid entries:
     + `blob:`: Matches all blobs, which includes file data returned by automation actions, such as `GetObject` returning items from Amazon S3 buckets, or images generated by Amazon Bedrock.
**Important**  
You must include `blob:` to your provided expression to allow file data returned by actions, even if your expression is `*`, you should update it to `* blob:`
     + `http://*.example.com`: Matches all attempts to load from any subdomain of `example.com`. Also matches `https` resources.
     + `https://source1.example.com https//source2.example.com`: Matches all attempts to load from both `https://source1.example.com` and `https://source2.example.com`
     + `https://example.com/subdirectory/`: Matches all attempts to load files under subdirectory directory. For example, `https://example.com/subdirectory/path/to/file.jpeg`. It does not match `https://example.com/path/to/file.jpeg`.

1. Choose **Save** to save your changes.