# Welcome

Welcome to Acho! We hope this documentation is helpful in navigating our platform. Feel free to contact us with questions.

## Introduction

Hi there! This documentation page will help you understand how to use Acho and unleash some of the more powerful things that Acho can accomplish for you.&#x20;

If you have not registered for an account, please visit[ https://app.acho.io/register](https://app.acho.io/register) to get your free account first. There are also in-app links to this documentation that may help you solve problems. <br>

## Quick links

Prior to diving into each documentation page, check out these import sections here.&#x20;

{% content-ref url="/pages/-MN-XI\_XXkcsT9xl7VMJ" %}
[Supported data sources](/acho-studio/resources/import-data)
{% endcontent-ref %}

{% content-ref url="/pages/-MF2tCalzUolE3EV4bm7" %}
[Apply an action](/acho-studio/data-prep-projects/applying-actions)
{% endcontent-ref %}

{% content-ref url="/pages/-MIG8BN2WIs1tFt8v2kK" %}
[All functions in Formula/SQL](/acho-studio/data-prep-projects/applying-actions/tools/sql-editor/supported-math-functions-in-formula)
{% endcontent-ref %}

{% content-ref url="/pages/-MHIisnHyWP1jUKuQ8UU" %}
[SQL Editor Queries](/acho-studio/data-prep-projects/applying-actions/tools/sql-editor/supported-sql-queries)
{% endcontent-ref %}

{% content-ref url="/pages/-MHXun4s3vtzyqgax29y" %}
[Export data](/acho-studio/data-flow/export-data)
{% endcontent-ref %}

{% content-ref url="/pages/WGBSVnOnl0pQcNVmH5ji" %}
[Popular Use Cases](/app-builder/popular-use-cases)
{% endcontent-ref %}

## How to contact us?

If you have further questions regarding Acho, please feel free to contact us. There are in general 3 ways to contact us online.

* **Chatbot:** located at the lower right corner of our site, you can chat with one of our team members anytime you want. Please allow up to 3 hours for responses.<br>
* **Email:** <contact@acho.io> For sales inquiries, or any questions more in detail, please use email to contact us while letting us know who you are, and where you work. Please allow up to 1 day for responses. We will try to answer your email question with higher clarity and more resources. <br>
* **Phone/video conference:**[ https://calendly.com/team\_acho/30min?](https://calendly.com/team_acho/30min?) For sales inquiries, and important service issues, please schedule a phone/video chat session with one of our team members. The Acho team is based in Boston, MA USA. Normal business hours in the Eastern Time Zone usually work for us.

The following pages will explain how you can best utilize Acho's products for your benefit. <br>


# What is Acho?

Learn about what Acho is and how it can streamline your data journey.

### **Why do you need Acho?**

Connecting, warehousing, cleaning, orchestrating, and productizing data can be very time-consuming and expensive. Without the right IT infrastructure and efficient interface, one may not be able to realize the full potential of their valuable data assets. &#x20;

* Acho is a data application development platform that can help you turn business data into mission-critical applications in automation, business intelligence, data science, internal tool, and client-facing products.
* Start from integrating different databases and third-party apps -- all in one place. You can then make endless changes to your database and share access with your teammates.
* As your analytics get more complex and sophisticated, Acho can help you run queries and manipulate the data tables in a low-code environment.&#x20;
* Turn your data into an interactive business app to extract more value and insights. You can build both internal and client-facing applications, allowing users to interact directly with your data.

### **The origin of Acho**&#x20;

The name for Acho is an acronym for ***A**I-driven, **C**ustom software with **H**igh-scalability, and **O**ptimized performance.* The idea behind Acho was incepted during our batch at Y Combinator in 2020. Since day one, our goal has always been to help teams build amazing applications that can drive results. &#x20;

The technology behind Acho is defined as ASSEMBLE, which stands for ***A**I-powered, **S**erverless, **S**calable, **E**vent-driven, **B**usiness **L**ogics **E**ngine*. We designed this system to help non-technical users build complex business applications at scale. In fact, Acho started building a Modern Data Stack for teams that needed to connect, transform, and orchestrate data. After the first year, however, we learned from many of our customers that traditional Business Intelligence dashboards are insufficient for delivering mission-critical services. In the following two years, we started investing in the ASSEMBLE project and aimed to help our customers scale beyond BI dashboards with custom applications.

### **How AI helps you build apps on Acho**&#x20;

To provide the most frictionless, and intuitive experience. Acho incorporates GPT's large language model to help users construct components needed for their applications. By interacting with Acho's App Builder via natural language, complex data feeds, business logic, and visual components can be generated within seconds. It drastically improves the efficiency of writing SQL, and backend/front codes, and therefore helps users of different backgrounds realize their vision faster than ever.

### **What're Acho's product offerings?**&#x20;

Acho is a platform for developing business applications in several different verticals Here're some examples for what Acho can do.&#x20;

1. **Automation**&#x20;

Automating business processes and workflows is one of the main capacities of Acho. By connecting data from your product systems (e.g. csv, xlsx files, relational/non-relational databases,   application APIs, remote folder, etc), you can construct a data pipeline for activating events via a third-party system.&#x20;

For example, many Acho customers use Acho to pull data from various systems and send it to their CRM application so their employees in sales, marketing, and customer support can receive fresh new data records of a source without manual entries.&#x20;

Another example is using a full-productized custom application to " activate" operational events. An accounting team for example can benefit from a "finance reconciliation" application that helps them approve, and reject payment by going through lengthy processes.&#x20;

Beyond automating data, and events, Acho's also very good at RPA. Within the App Builder, the "interaction" console is where digital workflows can be designed, deployed, and automated. You can do data scraping, email automation, interactive alerts, and many other applications with it.&#x20;

2. **Business Intelligence & Data Science**&#x20;

Being a data application development platform, Acho's primary focus is to productize data into interactive applications that can provide valuable services to the entire company. Business Intelligence is one space where Acho can add more value against the incumbent.&#x20;

Beyond just charts, visualizations, and simple reporting, you can use Acho to build highly sophisticated self-serve BI services with interactive filters, natural-language search systems, dynamic paging, real-time streaming services, access controls/privilege separation, and other advanced features.&#x20;

If you have an existing Python model, Acho can help you productize it within a few hours. No need to write complex API services or build a backend to host, tweak file configuration, and deploy your application on the cloud. Acho can host any Python model directly on top of the connected data resources on Acho.&#x20;

3. **Internal tool**

Building internal tools on Acho is easy. Whether it's a searchable database, customized CRM, ticket tracking system, APM, or something very complex, Acho can provide all the toolkits to help you develop a tool that can yield a high return on investment.&#x20;

There are many categories of internal tools Acho can deliver. The main value Acho can deliver is highly scalable customization. If you're unhappy with some of the off-the-shelf solutions in CRM, ERP, CMS, and HR, you can leverage Acho's App Builder to completely customize it to cater your own business needs. The customization may take much quicker than you think because of the hundreds of templates, and AI assistance on Acho.&#x20;

3. **Client-facing Product**

A client-facing product can be very complex and demanding. To fulfill ever-changing clients' requirements, a low-code system can be beneficial in terms of agility, flexibility, extendability, scalability, and affordability. It's hard to commit to a full-code project without a well-defined design, prototypes, and infrastructure. On Acho, client-facing products can be developed at a fraction of the cost of a full-code project while not sacrificing a lot in terms of flexibility, and scalability.&#x20;

Some notable client-facing products we've built include data terminals, SaaS platforms, progressive web apps (PWA), E-Commerce stores, Customer portals, Customer feedback & surveys, event registration, and management systems, Job listing & Applicant Tracking Systems, and more.&#x20;


# How does Acho work?

{% embed url="<https://youtu.be/FuOpnCtHHpI?si=0_d0s4e4GE2I7JlN>" %}

Acho is a data application development platform for teams to productize business data into valuable applications that can help scale business operations, and improve customer experiences. Acho has 3 fundamental pieces.&#x20;

1. The data infrastructure&#x20;
2. The data preparation layer (transformation, cleaning, orchestration, and automaton)&#x20;
3. The data application layer&#x20;

### **1. Data Source Integration (Resources)**

The first thing you would do on Acho Studio is to connect to your database. We have built connectors that will help you verify database connections instantly. See this list of data sources that we currently support.&#x20;

* Flat Files (CSV, TSV, TXT, Excel)
* Databases (MySQL, SQL Server, Postgre SQL, MongoDB)
* Applications (Salesforce, HubSpot, Shopify, Google Analytics, Google Sheets, etc.)
* API (custom API endpoints)

Each integration is connected to Acho Studio. Check out our Data Connector for more info on pulling data into Acho.&#x20;

### **2. Build projects with data resources (Data Prep)**

A data prep [project](/acho-studio/data-prep-projects/create-a-project) on Acho Studio is where you can access your data resource and build on top of it. Each project contains many "[tabs](broken://pages/-MBfI4djiuZ6kAFNUPVV)". Similar to your browser, you may use these tabs to access your data feed. On each tab, you will find many "[actions](/acho-studio/data-prep-projects/applying-actions)" on the toolkit bar. These actions such as filter, join, replace etc. are similar to a SQL query. When you apply one of these actions,  we will send in a query and change your table according to the action and values that you have input. You may apply as many actions as you want, and reset/undo them in sequence. Also, don't worry about losing tables in the process. All tables will be saved every step along the way.&#x20;

### **3. Observe and monitor data pipelines(Data Flow)**

After data has been connected, you can come to the Data Flow and make sure that there are no delays, breakages, or missing data in your pipelines. By leveraging the built-in data observation features, you can quickly identify where the pipelines may require extra attention and debug them within your Data Prep projects.&#x20;

### **4. Build interactive data application (Data App)**&#x20;

The Data App builder is the last stop of your data journey on Acho. Within the data app builder, you can practically build any system with your data connected. It's rather simple to get started with tables and charts. Though it can get pretty advanced when you start building more interactive applications with more services for your users. Feel free to check out our [live demo](https://acho.io/live-demo) page for some of the possible applications you can build.&#x20;

&#x20;


# Proof of Concept (PoC)

A PoC is a collaborative process of building and configuring the business system tailored to your specific needs. Here's a simple walkthrough of how our PoC process works.

1. **Create a free Acho account**&#x20;

Acho Studio is free to sign up. Please go to the [home page](https://acho.io/) and click on "Start for free", or on any of the sign up buttons to create a free account. The account creation does require a business email. Please let us know if you run into any issues.&#x20;

<figure><img src="/files/DBEmqWmnPx3alODXaDp0" alt=""><figcaption><p>Sign up for Acho</p></figcaption></figure>

{% embed url="<https://acho.io/>" %}

2. **Add a Resource**&#x20;

The account creation process should be pretty simple. As of 07/01/2024, you may run into an interactive tutorial. If you want to skip the tutorial, simply **refresh the page**.&#x20;

After that, you should be in Acho Studio's Resource page. Here, you can find the business system to connect for the Proof of Concept.&#x20;

For some advanced integrations, please hit "**Submit"** button so our Solution Engineer can set up the integration for you.&#x20;

<figure><img src="/files/b3971AVZd3BOD8KCYchq" alt=""><figcaption></figcaption></figure>

3. **Add Solution Engineer/Architect to your organization**&#x20;

Once you've submitted or connected the resources for the PoC, you can easily invite one of our SE/SAs to your organization to kick off the PoC process.&#x20;

1\. Click avatar at top right to open **Profile**

2\. Navigate to **> Organization**

3\. Click **Invite members**&#x20;

{% content-ref url="/pages/esYu5tywQiiC9HvLaOUk" %}
[Invite people to your organization](/organization/invite-people-to-your-organization)
{% endcontent-ref %}


# Get Started

To start building your first app, you can follow the following steps.

### 1. Connect with a data source as a [**Resource**](/acho-studio/resources)

Most data sources are supported here including flat files (.csv, xlsx, .txt, json), databases (MySQL, MongoDB, Snowflake, BigQuery, etc), and Applications (API, CRMs, ERPs, and more).

(Optional) Use [**Data Prep**](/acho-studio/data-prep-projects) to preprocess your data.

<figure><img src="/files/IN54w41BdnqFKOOX3ERk" alt=""><figcaption><p>Resourses</p></figcaption></figure>

### 2. Go to **App Builder (Data App)** and create a new app

Simply create a new app project in the “App Builder” section. Each app project would contain one unique application with a unique root URL, set of databases, front-end components, and services.&#x20;

<figure><img src="/files/6vDgsiVz9PHsBX4IH5tB" alt=""><figcaption><p>Data App</p></figcaption></figure>

### 3. Create a blank app, or build with a template.

<figure><img src="/files/CH1Fnniez7EGk9Nbjjxn" alt=""><figcaption><p>Create App</p></figcaption></figure>

<figure><img src="/files/BgARuZBm5QRAqHH6AiIT" alt=""><figcaption><p>The blank app you will generate if you choose blank app</p></figcaption></figure>

### 4. Construct pages

Next, you can construct the page layout by dragging any element from the **Create** panel and dropping it on the page. In this example, drag a table element to the page.&#x20;

<figure><img src="/files/LH8oxiW6Hy3jsjhKaI6W" alt=""><figcaption><p>Add elements to the page</p></figcaption></figure>

### 5. Select the resource

Select the resource data you added.

<figure><img src="/files/qKXKQAg5i40185fY47ca" alt=""><figcaption></figcaption></figure>

### 6. Preview

Click the [**Preview**](/app-builder/preview) button on the top right to see the result.

<figure><img src="/files/TXUJqCyO8kMKJ1jm2RlD" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/kLXSaptIzvo7TmXfHLxi" alt=""><figcaption><p>Previewing the app</p></figcaption></figure>

### 7. Publish

Once your app is constructed, you can click the [**Publish**](/app-builder/publish) button to [publish](/app-builder/publish) your app and [share](/organization/share-your-apps) the link with other people. &#x20;

{% hint style="info" %}
Explore more detailed tutorial in [Popular Use Cases](/app-builder/popular-use-cases)
{% endhint %}


# Core Concepts

Learn about the App Builder's core concepts. These definitions will guide you throughout this documentation and your building process.

## Data sources

### Data Source

There are 3 major types of data source in the app builder: [Table](/app-builder/app-construction/table),  [Metric](/app-builder/app-construction/metric) and [Query](/app-builder/app-construction/query)

1. **Tables**:  [**Tables**](/app-builder/app-construction/table) are the primary data sources in the App Builder. Tables is an intuitive way to access [Resources](/acho-studio/resources) and [Projects](/acho-studio/data-prep-projects) data in your app and interactive with them in the app.
2. **Metrics:** [**Metrics**](/app-builder/app-construction/metric) work as a data source that's ready for reporting and charting.&#x20;
3. **Queries**:  [**Queries**](/app-builder/app-construction/query) allow you write templated SQL queries to retrieve data from your data sources or modify your databases.<br>

### Data Store

[Data Store](/app-builder/app-construction/data-store) is a place where you can create variables to store data and flexibly use it anywhere. These variables can be accessed via [**accessors**](/app-builder/app-construction/accessors). The variables can also receive data via interactions within a specific scope. There are three levels of data in the Data Store:

1. **App Data:** Data is stored at the app level. All the elements, or pages in the app can access it or send an interaction to it.
2. **Page Data:** Data is stored at the page level. Only the elements on the same page can access or send an interaction to it.
3. **Element Data:** Data is stored at the element level. It can only be accessed by the element that stores the data. For some elements, such as Lists, their child elements (that is, elements placed within them) can get parent element data directly by declaring specific keys, such as `${$item}`.

##

## App Builder

The App Builder provides users with the **low code** tools to easily build custom web applications to streamline business operations. Web pages are built using a variety of drag-and-drop elements, each with highly customizable settings, so you can build the most relevant app for your purpose.

### App

An app is an application software that is stored on a remote server and runs in a web browser. They can be designed for a wide variety of use cases and functions.

### Collaboration

The app builder is designed for collaboration.&#x20;

#### Comment

#### Share

#### Collaborator

You can see who is collaborating with you at the real time.

### Page

[Pages](/app-builder/app-construction/pages) are just like a webpages of a website. An app is usually composed of several pages. For example, it can contain a sign-in page, home page, and profile page.

#### Device

The app builder accommodates three distinct layout options designed for various devices: **Desktop**, **Tablet**, and **Mobile**, all available at the same time for your convenience.

When designing layouts for tablets and mobile devices, the styling is exclusively applied within their respective scopes. As a result, each of the three devices can have its unique view without interfering with the others. This allows for best adaptation and optimization of your content for different screen sizes and devices.

<div align="left"><figure><img src="/files/LCwqj7AtMABCVQ36IeSk" alt="" width="332"><figcaption></figcaption></figure></div>

### Canvas

Canvas is the space where you arrange all the components across pages.

<figure><img src="/files/KleGCBo8veargpk9WPpu" alt=""><figcaption></figcaption></figure>

#### Canvas view

In Canvas View, all the pages are positioned on the canvas, and you can organize them with spatial logic. To edit a page in Canvas View, simply double-click on the page

#### Default view

The Default View is designed to focus on a single page at a time, offering enhanced zooming and scrolling experiences. This view helps you delve deeper into page development.

####

### Elements

There are 3 types of [Elements](/app-builder/app-construction/elements): Basic, Layout, and Form.

1. **Basic**: These are essential elements such as buttons, text, images, and charts.
2. **Layout**: Layout elements provide a formatted layout that you can reuse to organize the elements.
3. **Form**: Form elements can be used to capture user input, such as user-entered text, date pickers, and checkboxes

## Interactions

Data sources, elements, and your app communicate through [Interactions](/app-builder/app-construction/interactions).

Interactions consists of 2 components: **event** and **action**. When an event occurs, an action is carried out. For example, a click of a button can be an event to trigger an action to navigate to a different page.

### Event

### **Action**

An [action](/app-builder/app-construction/interactions/actions) consists of two candidate events. Simply put, it will send out an outbound event when it senses an inbound event. An action requires a source and a target. Usually, an action is defined on the source, which is an element that listens to the inbound event. For example, you can define an action on a button that sends out a notification when someone clicks this button.

### Custom API

### Plugin Store

### Automation:

**Scheduler Node** to trigger other actions or Nodes\
**Notebook Node** to connect to a Jupyter Notebook. Used for connect an algorithm or machine learning model.


# Overview

In this section, we’ll walk you through the development environment so you can easily find what you are looking for.

The App Builder consists of a left toolbar, canvas, top bar, right configuration bar, and an interactions panel at bottom.

<figure><img src="/files/8ajvjbzcIE4OLgJ7X1A6" alt=""><figcaption></figcaption></figure>

## Left Tool Panel

The left panel contains three tool tabs: **Navigator**, **Element**, **Data Node** and several advanced tool tabs **Data Store**, **Theme**, **Media Files**, **App Configuration**, **Plugin Store.**

1. **Navigator tab:** Under the Navigation tab, you’ll see a list of all pages in your app, where you can switch between pages or add new page.\
   Below page list, there is also an Element tree for current page. From the hierarchy, you can select elements by clicking on them and rearrange elements by dragging and dropping.\
   \
   ![](/files/6VTvCCcSk4l4EYbI5g4L)

2. **Elements tab:** Under Elements tab, you’ll be able to create new pages, elements, and data nodes by dragging and dropping from the panel to the canvas. \
   ![](/files/BE9QpnTsPPHuLdNWahod)

3. **Data tab:** The Data tab will list all of your data nodes. There are three kinds of Data Node: [Table](/app-builder/app-construction/table), [Query](/app-builder/app-construction/query), and others. \
   ![](/files/du3j6IM48IYQv0bX6OpQ)

4. **Data Store:**  [Data Store](/app-builder/app-construction/data-store) is where you store and manage variable data. You can view, declare, and manage data using in this app.

5. **Theme tab:** [Theme](/app-builder/theme) lets you choose and change color themes for your app. You'll find "color" and "color on" for each option, which represents the main color and text color on top, respectively. For example, with the below theme, a button will have a default blue color with white text on top.\
   ![](/files/P41KwBrdwY9dAySzs42p)

6. **Media Files**: Where you view access media files in [Resources](/acho-studio/resources)

7. **App Configuration**: [App Configuration](/app-builder/app-construction/app-configuration) provide app level settings.

8. **Plugin Store**: [Plugin Store](/app-builder/app-construction/plugin-store)

## Canvas

The canvas is your window into the structure of your app. In the canvas you will design your app’s interface.&#x20;

## Topbar

The toolbar is where you’ll find [App User Management](/app-builder/app-user-management), [Version Control](/app-builder/version-control), [Preview](/app-builder/preview), and [Publish](/app-builder/publish) options. You’ll also be able to rename your app by clicking it.

## Interactions panel

The Interactions panel is where you will define your [Interactions](/app-builder/app-construction/interactions). When an element is selected, you'll be able to add actions to its supported events.

## Right Configuration Panel

The right panel is for the configuration for the current selected page or element, including properties, CSS styles, etc.&#x20;

![](/files/v2j6r2y1HkFFiAsO9ExG)


# App construction

Build your app using our drag-and-drop interface.

## Create pages, elements, and data nodes

Adding a new page, element, and data node is as simple as dragging it into your canvas.

Open the Create tab from the right panel, find, and select what you’d like to add. Drop new pages and data nodes directly onto your canvas. Place elements onto an existing page.

## Rename pages, elements, and data nodes

See [Pages](/app-builder/app-construction/pages) for renaming pages under page properties.

For elements and data nodes, you can rename them under the Config tab.

<figure><img src="/files/M2j95pKNJnP4swsESgNV" alt=""><figcaption></figcaption></figure>

## Edit pages, elements, and data nodes

### Pages

In the default editing mode, you can drag elements directly onto the page. In canvas mode, click the Edit button on the right side of the page or double-click on the page to edit.

<figure><img src="/files/RJKumNWGljNImykouuoq" alt=""><figcaption><p>Drag a table in the default mode</p></figcaption></figure>

### Elements

Click on the element to edit. The configuration and style options will show up on the right configuration panel.

### Data nodes

Navigate to Data nodes on the left tools list, then find the node that you want to edit

<figure><img src="/files/luYZhu5BASWWJxLvYFnN" alt="" width="259"><figcaption><p>Data Nodes</p></figcaption></figure>


# App Configuration

An app needs to be properly configured before publishing.

Open app configuration panel with the <img src="/files/Vu4eS3m1XjxxYKBWiSJI" alt="" data-size="line">button at the left bar in the app builder

<figure><img src="/files/F1wOnLpktPy3ee9k35ij" alt=""><figcaption></figcaption></figure>

## Sign-in Required

Whether users need to sign in to view the page. See [App User Management](/app-builder/app-user-management) to see how this is used.

* If **Sign-in Required** is on(default), only signed in user can enter the app.
* If **Sign-in Required** is off, all users can enter the app.

![](/files/QP0eZo4wF3YiMwqpn4FA)

## Page Settings

You'll see four dropdowns: Home Page, Sign in Page, Onboarding page, Not Found Page (404), and Authorization Required Page (401).&#x20;

* **Home Page:** This page is set as the default home page when a user enters the app. Users will be directed to this page when they get into the app.
* **Sign in Page:** This page is designed specifically for user authentication. If a user tries to access a protected or restricted area of the app without being signed in, they will be automatically redirected to the Sign in Page. Here, users can enter their login credentials to gain access to the app's features and personalized content. See [Sign in page](/app-builder/app-user-management/sign-in-page) for settings of default sign in pages.
* **Not Found Page (404):** This page will be shown if the user attempts to navigate to a page in your app that does not exist. If a 404 page is not selected, a default 404 page will be displayed.
* **Authorization Required Page (401):** This page is displayed when a user attempts to access a resource or perform an action that requires special permissions or authorization. If a 401 page is not selected, a default 401 page will be displayed.

{% hint style="info" %}
Note: An Entry Page is required for every app. You can optionally set up Sign in, 401 and 404 Pages.
{% endhint %}

### Guest Isolation

{% hint style="warning" %}
Guest Isolation is only available when Sign-in Required is off&#x20;
{% endhint %}

Guest Isolation provides a separate session for each anonymous app user, so that they won’t interfere with each other. Turn on Guest Isolation will increase the cost and reduce the performance. For more information, please refer to [Guest Isolation and Private Session](/app-builder/app-user-management/guest-isolation-and-private-session)

## Advanced Settings

* #### Hide Acho Banner(Custom User Only)：

  **Hide ACHO Banner** allows users to toggle the visibility of the Acho banner at the bottom of the application's user interface.&#x20;
* #### Headless App(Creator and Custom User Only)：

  **Headless App** functionality allows the application to run without launching the user interface or browser window. Instead, it operates in the background, performing automated tasks or data processing. The Headless App usually work in conjunction with automation like a scheduler, enabling scheduled or event-based execution of specific actions or functions.

## App Metadata

App Metadata allows you to customize the title, description and thumbnail image of the app, to provide concise information of the app.

####

####


# Pages

Pages are the basic building blocks of your data app and display all app content.

Pages are specific component or section within an app, serving a particular purpose or providing specific content or functionality. Every app must have at least one page.

There are two kind of pages: Grid view pages (default) and Web view pages. Grid view is designed for ease of use, allowing you to control element layout through drag and drop. On the other hand, Web view is tailored for advanced layout customization. Here, you have the full flexibility to utilize CSS for creating more intricate layouts and exercising precise control.

<div align="left"><figure><img src="/files/I9wJrCJcXS0SlUnOovqc" alt="" width="375"><figcaption></figcaption></figure></div>

## Grid view pages

Grid view <img src="/files/90dyVIeFyA8PhzlMXE4G" alt="" data-size="line">is designed for ease of use, allowing you to control element layout effortlessly through drag and drop.

There are 24 columns in a grid view page, with each grid view unit width automatically adjusting to fit the view width. The height of a grid view unit is fixed at 12 pixels. Consequently, content within the grid view scrolls vertically along the Y-axis and expands horizontally along the X-axis.

## Web view pages

Web view <img src="/files/K7JL9qzsy2zA6WDetj8m" alt="" data-size="line">is more like traditional website, offering advanced customization options for layout design. Here, you have complete flexibility to leverage CSS for crafting intricate layouts and exerting precise control over the presentation.

By default, a Web View page has dimensions of 1920x1080 pixels, providing a standard canvas size for your web content.

## Settings

Select a page to alter its settings. Under Config, you’ll be able to change the name, size, background and path for a page. <img src="/files/90dyVIeFyA8PhzlMXE4G" alt="" data-size="line">indicates grid view and <img src="/files/K7JL9qzsy2zA6WDetj8m" alt="" data-size="line">indicates web view.

<div align="left"><figure><img src="/files/nQGMq0akXvM82kKR46WH" alt="" width="288"><figcaption></figcaption></figure></div>

**Name:** The name of a page, which will also be the tab title in the browser. Use the edit icon<img src="/files/fWEzg590AQOIUEoV4b80" alt="" data-size="line">to edit page name.

**Background**: 1. color: Use color selector or HEX code to select a fixed color for the page.\
&#x20;                     2\. image: Use image url to set a customized background image.

**Path:** The URL path suffix for a page determines its web address. It should adhere to URL rules, containing no spaces and using valid characters limited to letters (A-Z, a-z), digits (0-9), hyphens (-), underscores (\_), and slashes (/).

**Page Metadata:** The title, description and thumbnail image, enhancing search engine visibility and improves user experience.

## Supported Events

Pages have supported events with which to build [Interactions](/app-builder/app-construction/interactions). Below, we see the options for page events.

![](/files/LbWyDIYY2xEtKgXQg7nl)

1. **Before Render:** Triggered before a page loads or refreshes.
2. **After Render:** Triggered just after a page loads or refreshes.
3. **Leave Page:** When this is selected the action will be triggered when the user exits the page.

## Supported Actions

**Set page data:** Set page level data. See [Data Store](/app-builder/app-construction/data-store) for more on page data.

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Interactions

## What is an interaction?

Interactions are the building blocks for your web app’s functionality. They create communication between your data, elements, scripts, and web app, allowing you to build an interactive interface.

Click the interaction bar or the button next to the element to start adding interaction.

<figure><img src="/files/Cj90sNrKZwPi9zLkLvV4" alt=""><figcaption></figcaption></figure>

## What makes up an interaction?

An interaction consists of (1) an **Event** to trigger it, and (2) an **Action** to be performed. Interactions can be added to your pages, elements, and data nodes.

In the Interactions panel below the canvas, you'll be able to visualize the flow of an interaction.

The blue block represents the page, element, or data node that you are editing. Green blocks  represent a supported <mark style="color:green;">**event**</mark> that will trigger the action. Lastly, the **action** block contains the action that will be performed.

<figure><img src="/files/r7R2accwa9jU81KuvPni" alt=""><figcaption></figcaption></figure>

## Action Flow

You are able to add any number of actions to fulfill your requirements and arrange their logical relationships accordingly. See detailed information in [Ordering interactions with action flow](/app-builder/app-construction/interactions/ordering-interactions-with-action-flow)

<figure><img src="/files/0Cdghl9pFBdbqLyAa8Xk" alt=""><figcaption></figcaption></figure>

## Action input

Displays the schema of the input received by the action from preceding events or actions. Such input can be utilized within the current action. Consider the example below:

```json
code{
  "event": {
    "rowData": {},
    "tableData": "array",
    "rowKey": "string",
    "rowIndex": "number"
  },
  "prev": {}
}
```

In the context of an action triggered by a table row click event, the data from the clicked row can be accessed using the syntax `${rowData}`. See [Event payload](/app-builder/app-construction/interactions/event-payload) for more.

## Condition

This refers to the pre-requisites or requirements that need to be met for the action to execute. See [Add conditions to interactions](/app-builder/app-construction/interactions/add-conditions-to-interactions) for instruction.

## Advanced - Scheduler

This setting allows you to introduce a delay before the action's execution. Input the number of seconds you'd like the system to wait before proceeding.

*Example:* If you input `5`, the action will be executed after a 5-second delay.

## Copy and Paste Action

The Copy and Paste Action enables users to easily duplicate Action from one area and transfer it to another. This is particularly useful for replicating data or configurations without the need for manual re-entry.&#x20;

Select an action and press `ctrl + c` (`cmd + c`  on Mac) or click the copy menu below action to copy (e.g. the first Set App Data action).&#x20;

*Notice: The action flow after the selected action will be copied together.*

<figure><img src="/files/6z3YjfMWwY9SZgv7TPkx" alt=""><figcaption></figcaption></figure>

Then move to where you want to paste it, either to another Interactions Panel or to another app,  move the mouse and press `ctrl + v` (`cmd + v`  on Mac), then the copied action flow will be pasted at the current mouse position.

<figure><img src="/files/27RMxYFrmB2TpnsPndyn" alt=""><figcaption></figcaption></figure>

## Start adding interaction

Want to learn how to add an interaction? Click the following links to get started.

{% content-ref url="/pages/GQ4fFM7hYV4jx5D9g9iA" %}
[Add an interaction](/app-builder/app-construction/interactions/add-an-interaction)
{% endcontent-ref %}


# Add an interaction

Let’s take a look at how an interaction is built. Select a page, element, or data node you’d like to add an interaction to and a corresponding block will appear in the interaction panel below your canvas.

Note that interactions are added to the component that will be triggering the event. For example, if you’d like a button click to trigger an action, add the interaction to the button element.

### Events

Drag out from the right side of the first block to create an event block. A dropdown will appear for you to choose the Event that will trigger the action.

Below, we see options for page events. See [Pages](/app-builder/app-construction/pages) for more about how these events are triggered.

<figure><img src="/files/6s80QHSBT4qr3XNZWwo9" alt=""><figcaption></figcaption></figure>

Some [Elements](/app-builder/app-construction/elements)[ ](https://www.notion.so/Elements-a350730198194b20975f35f880a78232)have supported events, such as a button click or a table row click. View the information on each element to see what events they support.

### Actions

#### Add Action From Event

Once an event is selected, you’ll be able to choose an action to be performed. Drag out from the event block to create an action block. Click on the action block to select what type of action you'd like to perform.

<figure><img src="/files/KvGkrQZZ8GJ8eyi2hiqo" alt=""><figcaption></figcaption></figure>

These are the action options that you will see:

* **Navigation:** For navigating to a different page. See [Navigate to a different page](/app-builder/popular-use-cases/navigate-to-a-different-page) for how this works.
* **Element:** For performing an action on an element. When this is chosen, you’ll be able to select an element on your page. You’ll then see element-specific actions.
* **Data Node:** For sending request to Data Nodes. You can simple run the query, or change SQL parameters and re-run it to control the Data Nodes behavior.
* **Script Node:** For sending request to execute script,&#x20;
* **App:** For setting app data, or generating a unique ID at the app level.
* **Page:** For setting page data.
* **API Service:** For predefined API services, or user-defined services, that interact with Acho backend. This includes downloading data as a file, IAM management, and more.
* **Database:** For directly loading CSV or JSON data into database. This can be used to create table with corresponding data types for the data, or update new data into existing tables.

#### Add action from another action

You can also add an action after another action. If the new action is connected to the blue circle located above the former action on the right border, it means that when the former action is successfully completed, the new action will be triggered.&#x20;

On the other hand, if the new action is connected to the red circle located below the former action on the right border, it means that when the former action fails, the new action will be triggered. This is usually used to report an error message.

<figure><img src="/files/CKdZvtkhA4LVgYHHvOaf" alt=""><figcaption></figcaption></figure>

#### Action settings

On the right side of the Action panel, you'll see three icons:

1. The first shows you the event payload. See [Event payload](/app-builder/app-construction/interactions/event-payload) for more.
2. The second allows you to define a condition. Only when the condition is satisfied will the action be performed.
3. The third allows you to deploy a scheduler. The action will wait a certain time before it is performed.

   <figure><img src="/files/PcY29TU56TEkomxxiQWl" alt=""><figcaption></figcaption></figure>


# Add conditions to interactions

Conditions are used to control the action flow by determining whether certain action should be executed. The action won't be invoked if the condition returns false.&#x20;

You can find action condition at the top right corner of the [action panel](/app-builder/app-construction/interactions/add-an-interaction#add-action-from-event).&#x20;

<figure><img src="/files/fu6nbDAptMWbFtcsiz0P" alt=""><figcaption></figcaption></figure>

### Access data in condition

* #### Access event data

  `event.field_name`. For example, event.value >= 10 represent the condition that the value event emit is larger than 10. Other variables in action input is also available.
* #### Access element level data

  `field_name`
* #### Access page level data

  `#page.field_name`
* #### Access app level data

  `#app.field_name`. For example, a string app data named "current\_user", #app.current\_user == 'admin' represent the condition that current user is 'admin', meaning the action will only be invoked if current user is admin.
* #### Access query node data

  `#query_node_name`.  For example: `#query_node_name.length >= 5` represents the condition that the query node have more than 5 elements, meaning the action won't be invoked if the query node have less than 5 rows.

### Examples

<figure><img src="/files/sJ8ysNnndZcW2OPQDEUu" alt=""><figcaption><p>(Without Condition) Action after enter input</p></figcaption></figure>

Assume we have an action **Set text** after **Press Enter** for **Input**. For example, in the preview, we input a '2' in the box and press enter, then the text element is set to '4'.

Now, we add a condition `event.value <=10` to the action. By doing this the action will only be executed when the input value is no more than 10. Then we Click Update and Preview to test. In preview, when a number equal or less than 10 entered, the number will double and set in the text element. On the other hand, if a number larger than 10 is entered, no changes will occur.

<figure><img src="/files/IAQ2jWu3qMZHDK5cGh44" alt=""><figcaption><p>(Without Condition) Action after enter input</p></figcaption></figure>

<figure><img src="/files/GhQNfZJf4HzazwvsM8L7" alt="" width="240"><figcaption><p>Test in preview</p></figcaption></figure>


# Event payload

Information on event payloads -- in one place.

## What's an event payload?

An event payload contains information useful for distributing an event. This often includes data conveyed by the event that can be used to define the action parameters.

Each interaction contains an event payload, which varies depending on the element and the event.&#x20;

For example, suppose you'd like to click on a table row and set a text element to display the `id` of the row that's been clicked. The data for the clicked table row will be stored in the event payload, which you will be able to access with `${event.rowData.id}` to get the row's `id` to set your text element.

For each interaction, you can view the name and format of the data in the event payload by clicking on the <img src="/files/Q45Zvzq9j3zdls4PhZ5q" alt="" data-size="line"> button. All the event payloads are stored in the `event` key, while the `prev` key allows you to access the output from the previous action.

In this example, an interaction has been set up on a table. When it is clicked, its event payload will include an object called `rowData` containing data for that row, as well as `rowKey` and `rowIndex`.

![](/files/GQJqyAS5HU3EyKJgKg4z)

## Configuration panel vs transformer accessors

Accessors are used to obtain data from event payloads to use in an interaction. Accessing data in the event payload differs whether you're in the configuration panel or the transformer.

The configuration panel provides input boxes for each action parameter, mapping your input to its respective parameter. You'll be able to access the event payload with `${event.xx}`.

![](/files/enhEqkwz3yMicqvA1Qxi)

To switch mode to transformer, click on the `f(x)` symbol next to "Action Parameters". This will bring you to the transformer code editor. In this code editor, you'll be able to use JavaScript to further calculate and transform your data before setting your parameters. In the transformer, you can access the payload with `payload.event.xx`.

The `parameters` variable is an object with a name:value pair for each parameter. This object will contain the final values to return.

![](/files/vbFqtgMIBqw5vePXsHAn)

## Exception: event payload for query nodes

Event payloads for interactions on a data node also contains an object, `mountData`, which contains a key called `data` that contains your node's data. The data is stored as an array of JSON objects, each object representing a row with key:value pairs for each column.

![](/files/AOKXT2gjz82bxuSJA9io)

For example, if my data node has 2 rows, `mountData.data` will contain an array with 2 JSON objects:

{% code overflow="wrap" %}

```
[{"ticker":"AAPL","company_name":"Apple Inc.","exchange_short":"NASDAQ"},
{"ticker":"ABBV","company_name":"AbbVie Inc.","exchange_short":"NYSE"}]
```

{% endcode %}

Since the data for a data node is not stored in the `event` object, the accessor looks slightly different.

* In the configuration panel: `${mountData.data}`
* In the transformer: `payload.mountData.data`


# Ordering interactions with action flow

If you have an event that is triggering multiple actions, you can either have your actions run concurrently or sequentially.

* To run concurrent actions, drag out action blocks from the same event block.
* To run sequential actions, add additional blocks to the previous action.
* To deal with errors, drag out action blocks from the red circles.

<figure><img src="/files/DPcBqloqEXU3JcEVK1Vm" alt=""><figcaption></figcaption></figure>

* To add scheduler or conditions on an action, click the icons on the right panel.&#x20;

<figure><img src="/files/PcY29TU56TEkomxxiQWl" alt=""><figcaption></figcaption></figure>


# Transformer

Custom Javascript code in action flow

In a action of the action flow, transformer enable you to write custom Javascript function for data calculation and transformation within action flows, which provide you with limitless potentials.

Transformers serve as an alternative to input fields, and these two modes cannot be active simultaneously.

To switch to transformer mode, click the `ƒ(x)`. This action will open the transformer code editor, allowing you to write your custom JavaScript code.

<figure><img src="/files/Q9gL7cCSn6aXR4FbQbTO" alt=""><figcaption><p>Click to use transformer</p></figcaption></figure>

After entering the code editor, you'll find a transformer function. Please refrain from modifying the input and output definitions; instead, write your logic within the function.

The `payload` is an object that contains event payload data, determined by the element and event triggering it.

The `context` is used to retrieve data from query results or data store variables, much like the [Accessors](/app-builder/app-construction/accessors). To access query result data, use `context.getData("#query_name")`. For app data, use `context.getData("#app.variable_name")`, and for page data, use `context.getData("#page.variable_name")`.

<figure><img src="/files/1ZmkVg1CXujmuVZEWGl1" alt=""><figcaption></figcaption></figure>

The returned parameters object will be the parameters for the action. The fields are determined by the action type. Here is an example of using transformer to [App](/app-builder/app-construction/interactions/actions/app#set-app-data). `map_input` is a variable in App Data, and in the transformer, an object is constructed and assigned the value of the `map_input` variable.

<figure><img src="/files/rs3GY5vq811mxqdrpK8Y" alt=""><figcaption></figcaption></figure>

### Accessor in Transformer

Function `context.getData()` can be used to access data from user data, app data to Query node data.&#x20;

user data: `context.getData("#app.user")`

app data: `context.getData("#app.{{variable_name}}")` The variable need to be defined in Data Store&#x20;

Query node data: `context.getData("#{{node_name}}")`

### Event Data in Transformer

Values such as the date picker, selector or input box value are in the event data, which you can also access in the transformer.&#x20;

The Event Data is passed to the function through payload parameter. Typically, you can access the event data via `payload.event`

### Troubleshooting

You can use `console.log()` for troubleshooting. The output will be displayed in the browser’s console. For example, in Chrome, open Developer Tools, go to the Console tab, and view the logs. This works similarly to printf in C or print in Python. By logging variable values, you can track changes, identify bugs, and fix issues more effectively.

1. Add console.log() to display the variable you want to see in the transformer script and hit update.
2. Open preview
3. Open Developer Tools -> Console, clear the existing logs for better readability
4. Trigger the event
5. Check the new logs

<figure><img src="/files/827tSTNmjISqp7qgNiSC" alt=""><figcaption></figcaption></figure>


# Actions


# Navigation

Navigation actions are for users to move between various pages. There are four distinct navigation actions available, each serving a specific purpose:

* Go Back
* Go To Page
* Go To Page By Path
* Open Link

## Go Back

This action would get user return to the previous screen or page they were on, whether or not the previous page is in the app.

## Go To Page

This action will direct user to a certain page within the app.&#x20;

#### Dynamic page

If the page selected is a dynamic page (See [Set up dynamic routing](/app-builder/popular-use-cases/set-up-dynamic-routing)),&#x20;

<div align="left"><figure><img src="/files/2q22OaHhUyqE3NbcBfwk" alt="" width="317"><figcaption></figcaption></figure></div>

## Go To Page By Path

This action is a programmable way to direct the user to a page within the app. You can program the path and even add routeParams and routeQuery after the URL, providing more flexibility.

#### Example: Pass the current routeQuery of the current page to the report page.

In order to redirect users to "report" page and pass the routeQuery to it. First, set the "report" page path to page. Then, add the Go To Page By Path action on a button, set the Page Full Path to `report?reportDate=${#page.routeQuery.reportDate}` . The `${#page.routeQuery.reportDate}` represents an accessor to get the `reportDate` value from `routeQuery` object in current page data.

<div align="left"><figure><img src="/files/amwBUAvNm1Vanz0r3QUC" alt="" width="288"><figcaption><p>Set destination page path</p></figcaption></figure></div>

<div align="left"><figure><img src="/files/7LRAKtkZmAHBJHmaCpor" alt="" width="317"><figcaption><p>Set action page path</p></figcaption></figure></div>

## Open Link&#x20;

This action will direct user to the link, no matter it is in app or not.&#x20;

**Link**: Insert the URL you want to open

**Open In New Tab**: Check this option if you want the link to open in a new browser tab.


# Element

An Element action are used to modify a selected element, and perform various tasks such as set element data, set loading, set text set value.

You need to first select the specific element you wish to modify, and then choose the corresponding action from the available options, each type of elements is bond to different types of actions, see the detailed supported actions in [Elements](/app-builder/app-construction/elements).

If the Element action is triggered by an event from an element in a page, then the Element action would be restricted to only the element within the same page. If it is triggered by an app level component, such as a Data updated event from a Query, then you can select element in any pages.

Each elements support different actions, but there are two common supported actions: Set data and Set loading.

## Set Data

Set element data of the selected element. You need to set the variable in advance in data store. See more in [Data Store](/app-builder/app-construction/data-store)

## Set Loading

Set a loading animation to the selected element. Refer to [Set loading animations](/app-builder/popular-use-cases/set-loading-animations) for a detailed example.


# Data Source

Data source actions are used to dynamically fetch data from data sources or update data. There are three kinds of data sources in the app builder: Table, Metric and Query. Each data source supports different actions.

## Table

For **Tables**, there are two supported actions: **Get Table Data** and **Insert Table Rows**

### Get Table Data

This action retrieve table data from the datasource with search, filter, page and sort. It is used to create a searchable table, apply filters, change pages and implement sorting options to arrange the data in ascending or descending order based on selected columns.

* **Page Size:** Specify the number of records or items to display on each page when paginating through data. It determines how many results are visible at a time.
* **Page Number:** Enter the current page number when paginating through a large dataset.
* **Search Fields:** Specify the fields or columns within the data source that should be included in the search operation. Users can search for information based on the selected fields.
* **Search Value:** Enter the value or keyword that users want to search for within the selected search fields. It's the actual query used to retrieve specific data.
* **Sorting Field:** Choose the field or column by which you want to sort the data. It determines the order in which data entries are displayed, either in ascending or descending order.
* **Sorting Order:** Specify whether you want the sorting to be in ascending (e.g., A-Z) or descending (e.g., Z-A) order based on the selected sorting field.
* **Advanced Filters:** This field provides an option for applying more complex and customized filters to the data. It allows users to refine their data queries based on various criteria.

<div align="left"><figure><img src="/files/QLx9qjUD5CDTvb6GBkPJ" alt="" width="318"><figcaption></figcaption></figure></div>

### Insert Table Rows

Insert new records to the data source. This action is used to add fresh data entries or records into the designated data source. It is particularly helpful when you need to populate a data source with new information, whether you're collecting user input, importing data from external sources, or simply adding data manually.

## Metric

For **Metrics**, there is only one supported action: **Get Metric Data**

### Get Metric Data

This action retrieve data from the metrics result with search, filter, page and sort. It is used to create a searchable table, apply filters, change pages and implement sorting options to arrange the data in ascending or descending order based on selected columns.

* **Page Size:** Specify the number of records or items to display on each page when paginating through data. It determines how many results are visible at a time.
* **Page Number:** Enter the current page number when paginating through a large dataset.
* **Search Fields:** Specify the fields or columns within the data source that should be included in the search operation. Users can search for information based on the selected fields.
* **Search Value:** Enter the value or keyword that users want to search for within the selected search fields. It's the actual query used to retrieve specific data.
* **Sorting Field:** Choose the field or column by which you want to sort the data. It determines the order in which data entries are displayed, either in ascending or descending order.
* **Sorting Order:** Specify whether you want the sorting to be in ascending (e.g., A-Z) or descending (e.g., Z-A) order based on the selected sorting field.
* **Advanced Filters:** This field provides an option for applying more complex and customized filters to the data. It allows users to refine their data queries based on various criteria.

## Query

There are two frequent use actions supported for Queries: **Set SQL Parameter** and **Run Query**

### Set SQL Parameter

&#x20;This action is crucial for dynamic queries. **Set SQL Parameter** is used to change the parameter's value and rerun the query with the new parameter value, thereby altering the query result. Set SQL parameter can be very powerful and help accomplish a wide range of tasks.

The field in the **Set SQL parameter** corresponds to the parameters defined in the selected query. These parameters can have fixed values or dynamic values using accessors.

**Public**: Check this option if you want the action to be broadcast to all the sessions. If set to false, users won't be affected by other users' actions.

After setting sql parameter successfully, the query result will be updated. You can fetch the results using [Chart](/app-builder/app-construction/elements/table-and-chart/chart), [Table](/app-builder/app-construction/elements/table-and-chart/table) or [Accessors](/app-builder/app-construction/accessors).

For a practical example, refer to [Create a filter](/app-builder/popular-use-cases/create-a-filter)

<figure><img src="/files/sZ1X7nN8PumumXpVj9CZ" alt=""><figcaption><p>A query with parameter and A action to set SQL parameter</p></figcaption></figure>

### Run Query

Rerun Query to update the result. If you want to use the result of the query. Go the the query interaction, add actions after **Data Updated** event and use \`mountData.data\` to get query result.


# App

## Set App Data

This action allows you to set the value of a specific field in app data. Ensure that the variable you intend to modify has been defined in the data store. App data is often used to store temporary data, application status and intermediary values. Refer to [Data Store](/app-builder/app-construction/data-store) for more details.

* **Field**: The name of the variable you want to modify.
* **Value**: The new value to assign to the specified field.

Note: In the Preview Debugger, an error message reading 'Wrong field name' will appear if the variable is not defined. Please check the **datastore**<img src="/files/3F4uBvxCMzQ3JrMP3HhK" alt="" data-size="line"> to ensure that the variable is properly defined.

&#x20;![](/files/DZ4RtMKjV5Yiqm39tYRm)

## Run Code

This action allows you to run Javascript code, like Set App Data's transformer function, but it removes the hurdle of setting the app data every time. Moreover, this method supports asynchronous code, which executes the next node only after the asynchronous code is executed.

This method also supports throwing exceptions, transferring the status to the error handling process.

<figure><img src="/files/ra4z5HX3Qk2bulMCswdJ" alt=""><figcaption></figcaption></figure>

## Generate Unique ID

This action generates a Universally Unique Identifier (UUID). The UUID created is distinct and can be utilized in subsequent actions within your application.

To use the generated UUID in subsequent actions, add an action following this one and reference the UUID with the accessor `${prev}`.&#x20;

#### Example: Insert record to table with unique ID

Add a Generate Unique ID after the event you want to use to trigger the action.

<figure><img src="/files/mJeASGJl7RoqWUvJujZD" alt=""><figcaption></figcaption></figure>

Set up a query used to insert records to PostgreSQL, add a parameter in query to receive the simulation id. Then, after the 'Generate Unique ID' action, add a **Set SQL Parameter** action. Set the value of the parameter `simulation_id` to <mark style="color:red;">`${prev}`</mark>, representing the use of the result from **Generate Unique ID** as the simulation ID for the inserted record.

<figure><img src="/files/8r99bMDm8VM4gJ3Kw6O3" alt=""><figcaption></figcaption></figure>


# Page

## Set Page Data

This action allows you to edit the value of a specific field in page data. Ensure that the variable you intend to modify has been defined in the data store. Page data is often used to store temporary page data, page status and intermediary values. Refer to [Data Store](/app-builder/app-construction/data-store) for more details.

Page data is a page level concept. A page data can only be used and edited in the same page

* **Field**: The name of the variable you want to modify.
* **Value**: The new value to assign to the specified field.

Note: In the Preview Debugger, an error message reading 'Wrong field name' will appear if the variable is not defined. Please check the **datastore**<img src="/files/d1aE2r0rl4iHChNNUC9m" alt="" data-size="line"> to ensure that the variable is properly defined.

<div align="left"><figure><img src="/files/bAWFZ57jMJygp0pmmhW7" alt="" width="375"><figcaption></figcaption></figure></div>


# API Service

API services is the way to call apis in the application. API Services form the backbone of communication between your application and various APIs. They enable your app to interact with external services, ensuring data exchange and unlimited integration.

API services contains built-in API services and custom APIs.&#x20;

Built-in APIs are：

## Download File

Download a file as CSV or JSON from a query result. It is used for end users to download data from query results in their preferred format. This action is particularly useful for getting filterable and customized data based on user-specific requirements.

**Parameters:**

* **Data asset**: Select the data source that you want end users to download, currently only queries are supported
* **Format**: Decide whether the file should be in CSV or JSON format
* **Is Public File**: Toggle to make the file public
* **File Download Name**: The download file name

## Custom APIs

APIs from Plugin Store and Custom APIs.&#x20;


# Database

## Load CSV To Postgres

Load a CSV file into a PostgreSQL database. It could be combined with an Upload element, allowing end-users to upload CSV files directly into a specified table in a PostgreSQL database.

Parameters:

* **Asset ID Select:** Choose the target PostgreSQL database. This selection determines where the CSV data will be loaded.
* **Table Name:** Specify the name of the table in the PostgreSQL database where the CSV data will be loaded.&#x20;
* **File Path:** Provide the path to the CSV file you wish to upload.&#x20;
* **Create Table If Absent:** Activate this option to allow the system to automatically create a new table in the PostgreSQL database if the specified table name does not already exist. This feature helps in situations where the target table is yet to be set up.
* **Safe Mode:** Enabling Safe Mode treats all columns in the CSV as text data. This mode is useful for preventing data type mismatches and errors during the upload process, especially when the exact data types of the CSV columns are unknown or varied.
* **Schema Detection Sample:** This feature automatically detects and aligns the schema of the CSV file with the corresponding table in the PostgreSQL database. By default, the schema detection samples the first 1000 rows of the CSV file. This aids in accurately mapping CSV columns to the database table columns, reducing the risk of data inconsistencies.

## Load JSON To Postgres

Load a JSON file into a PostgreSQL database. It could be combined with an Upload element, allowing end-users to upload JSON files directly into a specified table in a PostgreSQL database.

Parameters:

* **Asset ID Select:** Choose the target PostgreSQL database.&#x20;
* **Table Name:** Specify the name of the table in the PostgreSQL database where the JSON data will be loaded.&#x20;
* **File Path:** Provide the path to the JSON file you wish to upload.&#x20;
* **Create Table If Absent:** Activate this option to allow the system to automatically create a new table in the PostgreSQL database if the specified table name does not already exist. This feature helps in situations where the target table is yet to be set up.
* **Safe Mode:** Enabling Safe Mode treats all columns as text data. This mode is useful for preventing data type mismatches and errors during the upload process.
* **Schema Detection Sample:** This feature automatically detects and aligns the schema of the CSV file with the corresponding table in the PostgreSQL database. By default, the schema detection samples the first 1000 records of the JSON file.&#x20;

## Example: Upload CSV to Postgres

Combining Upload and the Load CSV To Postgres API, you can build service for users to upload csv and preview them. This example serves as one of our template **Upload CSV template,** which you can find in the app builder.

1. Add An Upload element
2. Select event **Upload Successfully**
3. (Optional) Use Generate Unique ID to get a table name and save it in app data
4. Add the "Load CSV To Postgres" action. Use the path of the first uploaded file as the `Path` parameter.
5. (Optional) Add a "Set Text" action to display a message indicating whether the operation was successful.

<figure><img src="/files/kFl6p6Yl4FpDUJB7k1O6" alt=""><figcaption><p>Load CSV to Postgres in action flow</p></figcaption></figure>


# Media Service

## List files

This action allows users to fetch a list of files from a media file folder.

* **Folder Path:** The path of the folder from which the file list will be retrieved.&#x20;
* **File Name:** (Optional) If provided, the function will list files that match the specified file name or pattern. Leave blank to list all files in the folder.

## Download files

This action allows users to download specific files from a media file folder.

* **Folder Path:** The folder path where the target file is located.&#x20;
* **File Download Name:**  The download file name

## Delete files

This action allows users to delete files from a specified folder.

* **Folder Path:** The folder from which files will be deleted.&#x20;


# Table

**Tables** are the primary data sources in the App Builder. Tables is an intuitive way to access [Resources](/acho-studio/resources) and [Projects](/acho-studio/data-prep-projects) data in your app and interactive with them in the app.

A **Table** corresponds to either 1. A table in Resources, or 2. A tab in Projects. Resources and Projects could be stored in Cloud in an unordered, parallel way to optimize the ability to process big data. However, an application need clean neat and tabular data. That is where the concept of tables comes out. Table node allows you to directly access the data in resources and project and turn into Table, Charts and even Data science application, ensuring a hassle-free experience during app development.&#x20;

Tables needs no setup and ready-to-use in app construction. For example, [Create a table](/app-builder/popular-use-cases/create-a-table) and [Create a list](/app-builder/popular-use-cases/create-a-list) use a resource table.

### Where is Tables

![](/files/2uORxvYNjt7uUI9buXgL)

You can find a list of Tables at **Left Tool Bar - Data sources - Tables**.  For resources and projects that have multiple tables, click on them to expand. Hover on a table, you'll see a Preview button and a more button provides some quick operations including:

* [Interactions](#interactions)
* Use in [**Table**](/app-builder/app-construction/elements/table-and-chart/table):\
  Apply the **Table** to a table in the current app, or add a new table with the **Table** to the current app
* Use in [**Chart**](/app-builder/app-construction/elements/table-and-chart/chart):\
  Set data to this **Table** for a chart in the current app, or add a new chart with this **Table** to current app.
* Create [**Query**](/app-builder/app-construction/query)\
  Create a **Query** in current app.
* Default Page Size:\
  Set the default page size per page for this table. This setting determines how many rows will be requested from the database.

### Interactions

#### Actions

* **Get Table Data**

  Retrieve table node data with certain page, search and order.&#x20;

  * **Page Size**:  The number of results to display per page. A higher page size will show more results on a single page, while a lower value will show fewer.
  * **Page Number**: The specific page (starting from 1) of results to display based on the defined Page Size. For example, if there are 400 rows and the Page Size is set to 100, selecting Page Number 3 will show results 201-300.&#x20;
  * **Search Fields**: Specifies the database columns or attributes that should be searched. This helps in narrowing down the search to specific fields rather than searching across all columns.&#x20;
  * **Search Value**: The actual text or value to search for within the chosen Search Fields. The database will return results that match or contain this value in the specified fields.&#x20;
  * **Sorting Field**: Determines the database column or attribute by which the results should be sorted. For example, if you choose a 'Date' field, the results will be sorted based on dates.&#x20;
  * **Sorting Order**: Determines the direction of the sort for the selected Sorting Field. Common values include 'Ascending' (A-Z, smallest to largest, or oldest to newest) and 'Descending' (Z-A, largest to smallest, or newest to oldest).
* **Insert Table Rows**\
  Insert rows into table data source. Specifically:
  * **Resource Table:** Insert rows directly into the table in the resource that the current Table corresponds to.
  * **Data Prep Table:** Inserting rows into Data Prep Tables is **not recommended**. The table will be overwritten once the Data Prep is synced, and any rows you insert will be lost.

{% hint style="danger" %}
Warning: Sync operations like Resource [Full Refresh](https://docs.acho.io/app-builder/app-construction/pages/-Ma5NZ0C36Zzj1XXOrNa#3.3-data-sync-settings) and Save Data Prep result in irreversible loss of the inserted data.&#x20;
{% endhint %}

#### Events

* **Data Update**: Triggered when the data runs.
* **Data Update Error**: Triggered when errors occur as the data runs.

### Use cases for Tables <a href="#resource-groups-intro-usecases" id="resource-groups-intro-usecases"></a>

* [Tables](/app-builder/app-construction/elements/table-and-chart/table)
* [Metrics](/app-builder/app-construction/metric)
* [Charts](/app-builder/app-construction/elements/table-and-chart/chart)
* [Score Card](/app-builder/app-construction/elements/table-and-chart/score-card)
* [Query](/app-builder/app-construction/query)
* [Accessors](/app-builder/app-construction/accessors)


# Metric

**Metrics** are derived from [Table](/app-builder/app-construction/table) to represent calculated or aggregated fields and columns. Metrics can be an aggregated table, a series of meters or even a single value of meter.&#x20;

**Metrics** work as a data source that's ready for reporting and charting. All pages across the app can access metrics data.

## Create A Metric

**Metrics** are always created from **Tables**. To create a metric in an app, select **Data Source -> Table -> Create a Metric** or select **Data Source -> Metric -> Create Metric -> Select a Table source.**

<figure><img src="/files/y6ZiynsaIi0VLt0SPr6B" alt=""><figcaption><p>Two ways to create a metric</p></figcaption></figure>

There's three ways to create Metrics:&#x20;

1. Generate by AI: Type natural language to generate metrics with AI
2. Layer: No code GUI to perform summarize, filter, sort and limit to the resource
3. SQL: Write SQL code that program the metrics logic

### Generate by AI

The first and default way to create metrics is Generate By AI. In the metrics pane, you can describe what metrics you want using natural language prompt. Our AI metrics will generate the metrics according to your description and table schema. There are also five suggested prompt suggested to use.

The metric offers an original table preview before before you enter the prompt. You can also check the original table by clicking the eye icon<img src="/files/fVeoQekeMRPPWLI8KP2E" alt="" data-size="line">at the top at any time. After entering the prompt, it typically takes 5 to 30 seconds for the AI to generate the metrics. Then, the metric results will populate and replace the table preview at the bottom of the metric pane.

#### Iterate metric result

Occasionally, the initial metric may not align perfectly with your expectations. In such instances, you have the opportunity to reiterate metric by sharing additional information and your creative insights, allowing AI to modify the metric to your precise requirements. Simply type your requests within the same conversation. Our AI retains knowledge of previous conversations and metric results.

If you are still not satisfied with the result, you can switch to SQL mode and edit the SQL query yourself.

#### Clear conversation

If you want to start over, you can click Clear conversation. Our AI will then forget the current conversation and begin anew with your new prompt and the original table schema.

<figure><img src="/files/mwjqoeIfVltCYKFRjRga" alt=""><figcaption></figcaption></figure>

### Layer

Layer is a remarkable no-code tool that empowers you to weave logic into your original table within several clicks.

It offers support for several fundamental operations:

1. **Summarize:** This operation allows you to extract meaningful insights and summaries from your data.
2. **Filter:** With the Filter function, you can easily narrow down your data to focus on specific criteria or conditions.
3. **Sort:** Use the Sort feature to arrange your data in a structured and organized manner.
4. **Limit:** The Limit option lets you restrict your data to a specified range or quantity.

You have the flexibility to combine these operations in various ways, allowing you to adapt your data processing within the app builder to suit your specific requirements.

### SQL

You can use the query generated by AI and further edit it in SQL mode, granting you unlimited flexibility. However, if you are a deep SQL expert, [Query](/app-builder/app-construction/query) is designed for you to craft templated queries.

### Interactions

The interactions of metrics are completely inherited from the [Table](/app-builder/app-construction/table)

#### Actions

* **Get Metric Data**

  Retrieve table node data with certain page, search and order.&#x20;

  * **Page Size**:  The number of results to display per page. A higher page size will show more results on a single page, while a lower value will show fewer.
  * **Page Number**: The specific page (starting from 1) of results to display based on the defined Page Size. For example, if there are 400 rows and the Page Size is set to 100, selecting Page Number 3 will show results 201-300.&#x20;
  * **Search Fields**: Specifies the database columns or attributes that should be searched. This helps in narrowing down the search to specific fields rather than searching across all columns.&#x20;
  * **Search Value**: The actual text or value to search for within the chosen Search Fields. The database will return results that match or contain this value in the specified fields.&#x20;
  * **Sorting Field**: Determines the database column or attribute by which the results should be sorted. For example, if you choose a 'Date' field, the results will be sorted based on dates.&#x20;
  * **Sorting Order**: Determines the direction of the sort for the selected Sorting Field. Common values include 'Ascending' (A-Z, smallest to largest, or oldest to newest) and 'Descending' (Z-A, largest to smallest, or newest to oldest).

#### Events

* **Data Update**: Triggered when the data node runs.
* **Data Update Error**: Triggered when errors occur as the data node runs.

### Use cases for Tables <a href="#resource-groups-intro-usecases" id="resource-groups-intro-usecases"></a>

* [Tables](/app-builder/app-construction/elements/table-and-chart/table)
* [Charts](/app-builder/app-construction/elements/table-and-chart/chart)
* [Score Card](/app-builder/app-construction/elements/table-and-chart/score-card)
* [Query Nodes](/app-builder/app-construction/query)
* [Accessors](/app-builder/app-construction/accessors)


# Query

**Queries** allow you write SQL queries to retrieve data from your data sources or modify your databases in queries.&#x20;

**Queries** must be created from **Tables** and are only available in the current app. However, you can have multiple queries for the same tables.&#x20;

All elements across pages can interact with **Queries** through interactions, including trigger **Run Query** or **Set SQL Parameters**.

<div align="left"><figure><img src="/files/K5zzgOyXT3GM9qGDmIdq" alt="" width="375"><figcaption></figcaption></figure></div>

## Set up a query

**Queries** must be created from **Tables** and are only available in the current app. There are two methods to instantiate a query:

* **From Tables**
  1. Navigate to the desired table.
  2. Click on the More option <img src="/files/5l146X9ycVSNBcSYWcna" alt="" data-size="line">
  3. Select **Create Query** .\
     ![](/files/mY7mclwiHYxaj5uffXc6)
* **Adding from Query Tab**
  1. Go to the Query tab.&#x20;
  2. Click on <img src="/files/dp4IVj5QqI4rw9gTQlsR" alt="" data-size="line">**Add Query**.&#x20;
  3. Choose the table from which you wish to create the query.\
     ![](/files/XLSEO12rMHHPxzly4DgY)

### Edit Queries

After creating the queries, double click on it to edit.

<figure><img src="/files/6huQQ8yyrQa91FxBlxt9" alt=""><figcaption><p>Editing query</p></figcaption></figure>

1. **Queries Name:** In app name of your query
2. **Database Name:** Represents the database you are currently querying against.
3. **Data Directory:** Displays all the available tables across different databases within the same database type, including Acho-hosted and self-hosted databases. For example, in the PostgreSQL query, you can find all the available PostgreSQL databases, but it doesn't include other types of databases (such as MySQL). Also, you cannot query against tables across different PostgreSQL databases simultaneously.
4. **Query Pane:** The pane allows you to write queries. It supports writing a single query at a time. Currently, it doesn't support writing functions or procedures. Macro is supported to help you do complex operation [#macros](#macros "mention")
5. **Generate by AI:** Click on this button to access the AI panel, which leverages generative AI  to assist you in writing SQL queries. You can streamline the query creation process using natural language prompts.&#x20;
6. **Run:** Run the query in the Query Pane and display the query results in the above Table Preview. Note that it's only to run the query but won't save it and its results.
7. **Save:** Run the query and save all the changes (including the query, query results, and parameters).
8. **Parameter Pane:** This pane allows you to create parameters and their initial values. These parameters are dynamic and can be used in the Query Pane. See [here](https://app.gitbook.com/o/-MB_gcnULb42rxiDPWhi/s/-MB_fx7PCUqvFEdrucJC/~/revisions/4JlQ5nOGoRpO9W7fJVeb/build-your-apps/data-sources/data-nodes#set-up-parameters) to learn more about how to set up parameters.
9. **Table Preview:** When you run a query, the results will be presented in the Table Preview. Use the pagination below to switch page.

## How do queries work?

Each queries functions like a script, storing an SQL query. When triggered by other elements, the query node fetch information including database address from table node, then run the query, either retrieving data or modifying the database. If the query returns data, the data is stored in Acho's in-memory database, serving as a cache layer for your app. However if your statement is DML (UPDATE, INSERT, DELETE) or DDL(CREATE, DROP), no data will be stored in the query.

## Queries Syntax

The syntax of a queries is determined by the data source they connected

1. **Acho resource and Data Prep Projects**:  Acho resource and Data Prep Projects are replicated and stored in an Acho-hosted data warehouse. For query nodes connected to resources and the Data Prep Project, use BigQuery syntax. See which [statements](/acho-studio/data-prep-projects/applying-actions/tools/sql-editor/supported-sql-queries) and [functions](/acho-studio/data-prep-projects/applying-actions/tools/sql-editor/supported-math-functions-in-formula) you can use.<br>

   At present, it's recommended to use only SELECT queries in such queries. Any data modifications made using DML (UPDATE, INSERT, DELETE) or DDL (CREATE, DROP) may be overwritten when the data source is synced, resulting in the loss of those changes.<br>
2. **Direct Connector**: Query against your database directly. It allows you to query all data stored in your database and supports DQL (SELECT), DML (UPDATE, INSERT, DELETE) or DDL(CREATE, DROP). Different databases have their own SQL dialects and syntax. Currently, we support the following databases for direct access:\
   \- PostgreSQL\
   \- MySQL\
   \- Snowflake\
   \- MongoDB&#x20;

## Set SQL Parameters

Parameters are used for creating dynamic queries. They are like variables that can store any value and be inserted into queries. Their values can be changed via event actions **Set SQL Parameters.** See detailed example in [Create a filter](/app-builder/popular-use-cases/create-a-filter).

#### **1. Add new parameter**

Click the plus icon at the **Parameter Panel to** add new parameter. You need to specify name and datatype and Default value(optional but recommended).

![](/files/k2xqJxF79dKJUYbLozNR)

#### **2. Insert parameters in SQL query**

All parameters can be inserted anywhere in the query. The parameter replaces `{{parameter_name}}` with the value specified in the parameter.

Here are some examples:

Pass a string: (need quotes to represent it as string) &#x20;

```
SELECT *
FROM customers
WHERE customer_id = '{{customer_id}}'
```

Pass an integer or a number: (doesn't require quotes)

```
SELECT *
FROM customers
WHERE age = {{customer_id}}
```

Pass a column name: (doesn't require quotes)

```
SELECT {{category}}, COUNT(DISTINCT customer_id) AS n_customers
FROM customers
GROUP BY {{category}}
```

#### **3. Deal with arrays or objects**

If your parameter is an array, you have to use "macro" to turn the array or object into a format that the database can ingest.

Use an array to specify values in the IN statement

Suppose you have a parameter called `categories`. It's an array and contains three values.

```sql
{
categories: ["New", "Repeat", "Royal"]
}
```

Now, we want to create a query to filter the `customer` table and get all the customers in these three categories via the `IN` statement as shown below.

```sql
SELECT *
FROM customers
WHERE category IN ("New", "Repeat", "Royal")
```

However, the array cannot be passed to the query directly since the query doesn't need the square brackets. In this situation, we need to use "[macro](#macros)" to do some transformation to the array parameter. [Macro](#macros) is a templating language that can help you generate queries. It supports various functionalities, such as for loop, or conditional statement (if and else). In this example, we want to use the for loop to pass all the values in the array one by one and use `joiner()` the function in macro to concatenate all the values with a comma.

```sql
{% set comma = joiner() %}
SELECT *
FROM customers
WHERE category IN ( {% for category in categories} {{comma}} '{{category}}' {% endfor %})
```

You can also use an array to select multiple columns. Suppose you have a parameter called `columns`, which you can dynamically set by [**Set SQL parameters**](#set-sql-parameters).  By default, `columns` is an array that contains four column names.

```sql
{
categories: [
    "first_name",
    "last_name",
    "type",
    "last_login"
    ]
}
```

```sql
SELECT {{ columns|join(',') }}
FROM customers
```

## Macros

Macro is a templating language that enhances queries to make them dynamic. It supports various functionalities, including for loops and conditional statements (if and else).

See available macros template at <https://mozilla.github.io/nunjucks/templating.html>

## Accessor

To access a query elsewhere in the app, use `${#query_name}`. See details in  [Accessors](/app-builder/app-construction/accessors)

{% hint style="info" %}
You may need to rename your query to valid variable name to use it in accessor
{% endhint %}

<div align="left"><figure><img src="/files/jV48ZkcJep36yTJejBsp" alt=""><figcaption><p>A text accessing the query  'car_datebase'</p></figcaption></figure></div>

## Supported Events

![](/files/9OUAxaMDqrWl4f550433)

**Data Update:** Triggered when the query runs.

**Data Update Error:** Triggered when errors occur as the query runs.


# Data Store

In data store, located in the Left tool panel -> <img src="/files/odHYOxb9UEiGu8NYJjXB" alt="" data-size="line">Data Store, you can create variables to store data that can be accessed elsewhere via accessors.

## Data Level

There are three levels of data in data store:

1. **App Data:** Data is stored at the app level. All the data sources, elements, or pages in the app can access it or send an event to it.
2. **Page Data:** Data is stored at the page level. Only the elements on that page can access or send an event to it.
3. **Element Data:** Data is stored at the element level. It can only be accessed by the element that stores the data. For some elements, such as Lists, their child elements (that is, elements placed within them) can get parent element data directly by declaring specific keys, such as `${$item}`.

## How to create a data field

1. Navigate to the <img src="/files/odHYOxb9UEiGu8NYJjXB" alt="" data-size="line">**Data Store** on the left panel.
2. Find a level (Element, Page, or App) and click **New data field** button to create a new data field.
3. Follow the instructions to fill in all the fields. Below is the explanation for each field and option.\
   ![](/files/bhYYX4XykF9pTWd39QEO)

**Data Name:** What do you want to name the data field? This is the name of the variable you’ll use later for accessing your data.

**Data Type:** What data type will this variable take on?

* **String:** A sequence of characters or textual data, such as `customer`. A string can have special characters or numbers. For example, `The valuation is $40B`.
* **Number:** A numerical value, such as `123`. Note that the numeric data cannot contain any special characters, such as commas, or dollar signs.
* **Array:** An array is used for storing multiple values in a single variable and displays within square brackets, such as `[1,2,3]`.
* **Object:** An object is a collection of properties that are defined as a key-value pair and specified within curly brackets, `{}`. A property key (name) is always a string, but the value can be any data type. For example, `{"name":"Steven", "age": 25, "interests":["Photography", "Hiking"]}`

**Storage Type:** Where do you want to store your data?

* **In Memory:** The data is stored temporarily. Every time users refresh pages, the data will reset to the initial value.
* **Session Storage:** The data is stored only during a user’s session. The data is persisted only until the browser or tab is closed. Each time a new session is opened, the data is reset.
* **Local Storage:** Data is stored in the user’s browser. The data is persisted until the user manually clears the browser cache or until your web app clears the data. If the user changes to another browser or computer, the data is no longer persisted.
* **DB (database):** Data is stored in a database (MongoDB). The data is always persisted, no matter if the user closes the browser or changes to another computer. To reset the data back to the initial value, you can either send an interaction or adjust it manually in the App Builder.

**Data Value:** The initial value of the variable. Data value can be empty but must follow the format of the selected data type. For example, if the data type is a number, the initial value should be a number like 1, 0, -15.&#x20;

## Access or declare data

In the App Builder, you can use your data store in the configuration panel or the interaction transformer via accessors. Accessors are a way for users to fetch a variable in a specific format.

Suppose you created a variable called `customer_id` in the app data and want to let a text element display the app data. In this case, you can use `${#app.customer_id}` in the text element. `#app` means to look up data at the app level. `customer_id` represents the data name or the variable name stored in the app data. `${}` tells the system to look for specific data.

<div align="left"><figure><img src="/files/j0qtQJX1pyUsRFwZzHoA" alt="" width="286"><figcaption><p>Create a variable called <code>customer_id</code></p></figcaption></figure></div>

In fact, all the app data is stored in a JSON object. Another way to think about it is that `${}` refers to a key in the JSON object. `#app` is the object name and `customer_id` is one of the keys in the object.

### **Access data in the configuration panel**

* App data: `${#app.data_name}`
* Page data: `${#page.data_name}`
* Element data: `${data_name}`
* Query result: `${#query_name}`

Example: Given we already have app data named "stock\_price" whose value is `70`. In a text element, we enter `Price: ${#app.stock_price}`, then in the app preview, the element will look like "Price: 70".

<figure><img src="/files/kS6U49ZntwBgIVHPjvHk" alt=""><figcaption></figcaption></figure>

### Access data in the t**ransformer**

In the interaction transformer, you can use a function called `context.getData()` to access app/page/element data instead of using `${}`.

* App data: `context.getData("#app.data_field")`
* Page data: `context.getData("#page.data_field")`
* Element data: `context.getData("data_field")`

If you are interested in using transformer, please see tutorial: [Update app data using accessors](/app-builder/popular-use-cases/update-app-data-using-accessors)

{% hint style="info" %}
Note: Accessing element data doesn’t require a `#` to define the data level. Since only the element can access its element data, it can be used by the element directly.
{% endhint %}

## Set or change data via interactions

You can send data from data sources or elements to data store via interactions.

### Set up app data

1. Create an interaction.
2. In **Action**, choose App > Set app data.
3. In **Action Parameter**, specify the data field that you want to change and the new value.

### **Set up page data**

1. Create an interaction.
2. In **Action**, choose App > Set page data.
3. In **Action Parameter**, specify the data field that you want to change and the new value.

### Set up element data

1. Create an interaction.
2. In **Action**, choose Element > Specific element > Set value.
3. In **Action Parameter**, specify the data field that you want to change and the new value.

{% hint style="info" %}
Note: Setting up an event to set app/page/element merely changes values in the data fields. It does not create a new variable. Remember to create a data field first before setting up your interactions.
{% endhint %}


# Elements

Elements are the components that make up your app's interface.

## Copy and Paste Element

### Copy

Select an element and press `ctrl + c` (`cmd + c` on Mac)  to copy the current element.

<figure><img src="/files/XLOvB8R0avHVZWa3qTxN" alt=""><figcaption></figcaption></figure>

### Paste

1. Move to the location you want to paste it to, either under another element of the current page, or in another page or another app.&#x20;
2. If you want to paste it underneath another element then select the element and press `ctrl + v` (`cmd + v` on Mac) , then the copied element will be pasted underneath the element you selected&#x20;
3. If you don't have any element selected, press `ctrl + v` (`cmd + v` on Mac), then the copied element will be pasted at the bottom of the current page.

*Notice: The Built-in pages and advanced pages can't be pasted directly into each other.*

&#x20;![](/files/jRMZ7v45zJ4rTYLGgRek)

{% content-ref url="/pages/qOrjKgTXvhC8ki6ChtrZ" %}
[Web Elements](/app-builder/app-construction/elements/web-elements)
{% endcontent-ref %}

{% content-ref url="/pages/Evwy5oxhxBvl4O1QePOD" %}
[Form Elements](/app-builder/app-construction/elements/form-elements)
{% endcontent-ref %}

{% content-ref url="/pages/KcGFqGrySne1quatmp0x" %}
[Layout Elements](/app-builder/app-construction/elements/layout-elements)
{% endcontent-ref %}


# Table & Chart


# Searchable Table

<div align="left"><figure><img src="/files/OcQiX1K1cXyOh8lKMV0l" alt="" width="290"><figcaption></figcaption></figure></div>

Searchable table is a table to display data with built-in **Search**, **Sort** and **Pagination** functionality. It is designed to helps you quickly build down searchable database.

Searchable table now support [Table](/app-builder/app-construction/table) and [Metric](/app-builder/app-construction/metric). Please use universal **Table Element** for [Query](/app-builder/app-construction/query) to achieve more flexible experience.

## Property

<table><thead><tr><th width="193">Name</th><th>Description</th></tr></thead><tbody><tr><td><strong>Data source</strong></td><td>Select a data source to display its data.</td></tr><tr><td><strong>Columns</strong></td><td>Columns to display in the table.</td></tr><tr><td><strong>Default value</strong></td><td>Default searching value</td></tr><tr><td><strong>Current page</strong></td><td>Default page to display</td></tr></tbody></table>

## Supported Events

<table><thead><tr><th width="205">Event</th><th>Description</th></tr></thead><tbody><tr><td>Search</td><td>Triggered when a search is performed.</td></tr><tr><td>Page change</td><td>Triggered when go to a page.</td></tr><tr><td>Page Size Change</td><td>Triggered when set a new page size.</td></tr><tr><td>Sort Change</td><td>Triggered when sort buttons on the header is clicked.</td></tr><tr><td>Row Click</td><td>Triggered when a row in the table is clicked.</td></tr><tr><td>Get Data Error</td><td>Triggered when get table data API on table node is failed.</td></tr></tbody></table>

## Supported Actions

<table><thead><tr><th width="205">Event</th><th>Description</th></tr></thead><tbody><tr><td></td><td>Triggered when a search is performed.</td></tr><tr><td></td><td>Trigger</td></tr><tr><td></td><td>Triggered when set a new page size.</td></tr><tr><td></td><td>Triggered when sort buttons on the header is clicked.</td></tr><tr><td></td><td>Triggered when a row in the table is clicked.</td></tr></tbody></table>


# Table

You can use a table element to customize how you present a table from a data source (**Table**, **Metric** or **Query**).

{% hint style="info" %}
See [Create a table](/app-builder/popular-use-cases/create-a-table) for a detailed tutorial
{% endhint %}

## Properties

<div align="left"><figure><img src="/files/BvCr8i67rVW4rCcDBnEa" alt="" width="290"><figcaption></figcaption></figure></div>

**Data source:** Select a data source to display its data.

**Columns:** Columns to display in the table.

## Populating the table

When you select a data source for the table element, the entire data table will be displayed by default. You can use the blue template area to set configurations that will apply to all columns.

<figure><img src="/files/qCg4VcKFBz8GZ6wqkAn2" alt=""><figcaption></figcaption></figure>

You can further modify your table by customizing the structure of each individual column under Config -> Property

## Hide a column

To customize a column, click on <img src="/files/W75ufRV5iMunLCDfzGdd" alt="" data-size="line">under Columns.

![](/files/NLF1CzRzOxlTaYAIIoVW)

Click on the new column, which will open up its configuration.

<div align="left"><figure><img src="/files/NZFp2tVr00tyCIQESMY4" alt="" width="326"><figcaption></figcaption></figure></div>

**Name:** Display name of the column.

**Key:** Name of the column in your data.&#x20;

**Width:** Width of the column in pixels.

**Pinned:** Set whether the column will be fixed to the left, right, or not fixed.

**Fixed Height**: Toggle off to allow automated height that fit the cell content

**Sort**:  Add a sort button on the column header. When user click sort buttons, event '**Sort Changed**' will be triggered. Add interaction on the table to enable the event triggers data source sort.

**Hide:** To hide a column, click on the ![](/files/kYZOJQvnYLH6mCOP0Icx) symbol.

To re-order the columns, click and drag on the 6 dots on the left of the column.

<figure><img src="/files/vKA9JYQeTv7IPn80ycvR" alt=""><figcaption></figcaption></figure>

When a new column is added, a new field will appear in your table element for you to configure the column.

Use `${$value}` to access values for that column’s key. Use `${$row.column}` to access values for that row from other columns in your data.

In the above example, the Product column will display both the id and name of the product, while the Stock column will contain the stock number.

## Element Styles

**Header and data background color:** Background color for the header row and data rows.

**Header and data color:** Color for the header row and data rows.

**Hover background color:** Color for when user hovers over row.

**Border color:** Color of the table border.

**Border width:** Width of the table border in pixels.

**Stripe:** Toggle on to display a stripe table

**Vertical Border:** Toggle on to display vertical grid borders

**Empty text:** Text that will be shown when the table has no data to display.

![](/files/My2oUG35bR43S0YAabZ6)

**Header Spacing and Cell Spacing:** Set padding for header and data cells.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

**Row Click:** Triggered when user clicks on a row.

* You’ll be able to use the values in the clicked row. They’re stored in an object called `rowData` in the event payload. To access a value, use `${event.rowData.column}`. See [Event payload](/app-builder/app-construction/interactions/event-payload) for more.

Sort Change:&#x20;

## Supported Actions

**Set Table Data:** Set data for the table with an array of JSONs.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Chart

The **Chart** element in Acho app builder provides a streamlined solution for data visualization serving various purposes, from business reporting, intricate business intelligence analytics to data science project.

<figure><img src="/files/utFrbhYIXKoHCD1mBUe4" alt=""><figcaption></figcaption></figure>

## Configuration

In the Chart configuration, there are three distinct tabs Property, Chart Styles and CSS, each responsible for a specific level of configuration.&#x20;

![](/files/TbtvQsM25248YHMflAAM)

### Properties

Properties are the key options for constructing a chart.

**Data source:** Specify the data you want to visualize in the chart. The data source could be Table Node, Query Node, App data and Page data. For App data and Page data, it should be structured as an array of observations. Only for the Table Node, the system will automatically process and transform the data into a format suitable for chart construction. See  [Build a chart from Table Nodes](/app-builder/popular-use-cases/build-a-chart-from-table-nodes) for details.

**Chart type:** Choose a chart type to load a template. Options include: Line Chart, Stack Bar Chart, Grouped Bar Chart, Pie Chart, Area Chart, Scatter Plot, Heatmap, and Choropleth Map.

**Dimension:** Dimensions are qualitative values. They categorize and label data. For example, in a dataset containing sales figures of different products, 'Product category' could be a dimension. It is the 'what' aspect of your data, providing a context in which the numbers (metrics) can be understood.

**Metric:** Metrics are quantitative values. They provide measurable data to answer "How much?". For instance, in the previous example, the number of units sold would be the metric. Metrics provide the actual numbers that you'd typically plot on a chart to understand magnitude, trends, or comparisons.

### Chart Styles configuration

#### Basic:

All chart types except Choropleth Map will have and x-field and y-field under the Basic section. By default the chart automatically select the first suitable Dimension and Metric as X-field and Y-field.

![](/files/1mcqqsa2lfmSJFxsPOe5)

**X-Field:** Name of the data column to use for the x-axis (horizontal variable).

**Y-Field:** Name of the data column to use for the y-axis (vertical variable).

Some chart types may have additional basic fields to define.

**Breakdown field(Z-Field):** This field allows for a further breakdown or categorization of the data, providing an additional dimension for analysis.

**Size**(Scatter Plot): The name of data column to use for the size of points in scatter plot.&#x20;

#### X-Axis and Y-Axis configuration

![](/files/uWncjfFennLw9cM36hfG)

X-axis and Y-axis configurations are for the information present on the two axis, mostly they follows d3 styles, see[ D3 docs](https://github.com/d3/d3-format) for more details:

* **Scale**: Choose how data is distributed. linear, log, pow or sqrt
* **Position**: For the X-axis, decide if it appears at the 'Top' or 'Bottom'. For the Y-axis, set its position to 'Left' or 'Right'.
* **Title**: Define the axis name and its appearance parameters such as its anchor point and color, etc.
* **Line**: Customize the main axis line by setting its end cap style, color, and level of opacity, etc.
* **Tick**: Customize the small axis marks, by setting its count, tick color, the way they're formatted.
* **Label**: Customize the text appearing alongside the axis like label font, label align, label rotation, label color, etc.
* **Grid**: Decide whether you want to display gridlines. If so, you can modify their color, style, and width, etc.

#### Title

Options for configuring the title and subtitle of the chart include settings for orientation, alignment, anchor, rotation, color, displacement values (dx, dy), font type, font size, text limit, and offset.

#### Marker Label

Marker labels are text annotations that are placed near data points or markers to provide additional information about those points, you can customize the Text, Offset, Font, Font size, Text align, Text baseline, Text rotation, Text Color, Label z-index.

#### **Legends:**

Whether the legend is displayed and its format, title, color, etc.

#### Chart Tooltip

The tooltip that pop-out when clicking the data point/area in the chart. You can customized the content and format of the tooltip.

### CSS&#x20;

General CSS styles like space, padding.

## Supported Events

Choose a chart type to view the corresponding supported events

## Supported Actions

**Render:** Send data in an array of JSONs to display on the chart.&#x20;

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Score Card

The score card, or sometimes called KPI indicator, iis primarily used to display metrics that represent performance indicators. This visualization element typically highlights crucial data points that help in understanding business's overall performance or specific business aspects. It can be designed to show not just the current value of a metric but also its change or trend over a specified period.

<div align="left"><figure><img src="/files/S56eIiADhCEf9WYSoyMY" alt="" width="328"><figcaption></figcaption></figure></div>

Regarding data sourcing, the scorecard is capable of utilizing a [**Metric**](/app-builder/app-construction/metric) or [**Query**](/app-builder/app-construction/query), and while it also supports a **Table**, this is not recommended. This is because it displays the value of the first row from the selected column, as specified by the "Display Column" setting. Primarily, aggregation occurs within a **Metric** or **Query**, and the scorecard displays this aggregated value. This approach ensures a focused and clear presentation of the most pertinent data.

### Properties

Data source: Select the data source of the score card

Display column: Select the column field of the data you want to display

Title: A short text describing the value

Prefix: An optional text or symbol placed before the value, such as $

Suffix: An optional text or symbol placed after the value, used to provide context or units (e.g., %, kg, hrs).

Footer: Additional information or commentary about the displayed data, such as a brief note on the data source, the time frame of the analysis

<div align="left"><figure><img src="/files/Z70Np0cY2J7HNAuCO64N" alt="" width="375"><figcaption></figcaption></figure></div>

### Supported Event

No event supported

### Supported Action

No action supported


# Form Elements

These elements can take in user inputs.

You have the option to wrap the following elements with [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form). These elements will send their output to the closest form that it's nested under. That form can hold the value for later use.&#x20;

If you need instant feedback for some inputs, you don’t need to wrap it in a Form. However, if you want the users to fill out a form, for example, a sign-in form with email and password, you have to use Form to achieve it.&#x20;

{% content-ref url="/pages/l0e7H7R7PTLOfYpwKZUZ" %}
[Checkbox](/app-builder/app-construction/elements/form-elements/checkbox)
{% endcontent-ref %}

{% content-ref url="/pages/oQdNOFoSZVjS25fIGINt" %}
[Date Picker](/app-builder/app-construction/elements/form-elements/date-picker)
{% endcontent-ref %}

{% content-ref url="/pages/deRxWI1KQxApASmyXn6n" %}
[Custom Form](/app-builder/app-construction/elements/form-elements/custom-form)
{% endcontent-ref %}

{% content-ref url="/pages/UQ6rW1R3G1iFWfrQmIzJ" %}
[Input](/app-builder/app-construction/elements/form-elements/input)
{% endcontent-ref %}

{% content-ref url="/pages/jY942nrQINkbZq1OxM0a" %}
[Multiselect](/app-builder/app-construction/elements/form-elements/multiselect)
{% endcontent-ref %}

{% content-ref url="/pages/ZeKLsbeZ7LJzgAor37W2" %}
[Radio Button](/app-builder/app-construction/elements/form-elements/radio-button)
{% endcontent-ref %}

{% content-ref url="/pages/LdUvR3pbjl4cimMD8ZiL" %}
[Radio List](/app-builder/app-construction/elements/form-elements/radio-list)
{% endcontent-ref %}

{% content-ref url="/pages/fQHmHN9WZ4lyChHEHbfq" %}
[Rich Text Editor](/app-builder/app-construction/elements/form-elements/rich-text-editor)
{% endcontent-ref %}

{% content-ref url="/pages/LAiZkKybUKiPujx9IDbe" %}
[Select](/app-builder/app-construction/elements/form-elements/select)
{% endcontent-ref %}

{% content-ref url="/pages/T9VMMr1FmUyb6u0ydpfH" %}
[Switch](/app-builder/app-construction/elements/form-elements/switch)
{% endcontent-ref %}

{% content-ref url="/pages/XrfoiS3DyqrE1YDVJj9C" %}
[Textarea](/app-builder/app-construction/elements/form-elements/textarea)
{% endcontent-ref %}

{% content-ref url="/pages/8Deyeh7xXCgJytxBpNzj" %}
[Broken mention](broken://pages/8Deyeh7xXCgJytxBpNzj)
{% endcontent-ref %}


# Form

A form collects input values from form item elements, serving as filters, data entry, and more. It allows user to submit a series of input value on one click, and triggered other interactions with the gathered user input.

## Add Form elements in Form

<div align="left"><figure><img src="/files/2HR6XAhSuib6HdYimQGa" alt="" width="375"><figcaption></figcaption></figure></div>

Click **Add an item** to add a form element and configure it. It's crucial to define the **Form field name** for the form element. The input for each form element will become a property in the return object when the form is submitted, with the **Form field name** serving as the corresponding key.

{% hint style="info" %}
If there is a conflict with the **Form field name** (the key), only the first form element will function as expected.
{% endhint %}

## Property

**Form elements**: The form element items in the Form.&#x20;

**Default form value**: The object used to the default value for forms.

**Submitting**: Toggle on to start submitting animation. This can be used with Action **Change Submitting Status** to prevent duplicate submissions.

**Disabled**: Toggle on to prevent all form elements to be edit.

## Supported Event

**Submit**: This event is triggered when the form is submitted. There are two ways to trigger the submit event:

1. When a user clicks the built-in **Submit** button.
2. When an interaction on another element is set up to submit the form. To do this, a **Submit form** action should be configured on the element.

Either way, the form elements input value will be collected, and can be utilized as <mark style="color:red;">`${event.form}`</mark> as an object in the following actions.

**Reset**: This event is triggered when the form is reset.

**Form Value Change**: This event is triggered when users edit the values of form elements.

## Supported Actions

**Submit form:** Submit the form (trigger its Submit event).

**Change Submitting Status:** Start or end submitting animation. This can be used to prevent duplicate submissions.\
![](/files/8YYhL0FC8CnQ7UFOT7H4)

**Set form value:** Set the value of form object.

**Set form item value:** Assign a value to a specific item within the form. This feature allows you to modify the value of individual form elements. The **Field** parameter corresponds to the **Form field name** of the target form element.

**Reset form:** Reset form item values.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).


# Search Bar

Search Bar is an element group thats made up of an [Input](/app-builder/app-construction/elements/form-elements/input) and a [Button](/app-builder/app-construction/elements/web-elements/button).

<div align="left"><figure><img src="/files/4LEY09EJZozgLFd1CEvE" alt="" width="375"><figcaption></figcaption></figure></div>

The search bar makes it simple to use the user-inputted value in interactions. The input value is stored as a string in the Event Payload. For an example, see [Create a filter](/app-builder/popular-use-cases/create-a-filter).&#x20;

## Properties

<div align="left"><figure><img src="/files/9oVnRjsxp93zAJQTVr3J" alt=""><figcaption></figcaption></figure></div>

**Click button to search:** Users can always initiate a search by pressing the Enter key. With this toggle activated, they will also have the option to initiate the search by clicking the search button. If this toggle is deactivated, the button will be both disabled and hidden.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

**Search:** Triggered when a user clicks the search button.

* The inputted value is stored as a string in the Event Payload. You’ll be able to access it using `${event.value}`

## Supported Actions

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Checkbox

Checkbox lets users select one or more options from a group of options.

<div align="left"><figure><img src="/files/P81pCGE28rZ0vk9p0CxY" alt="" width="356"><figcaption></figcaption></figure></div>

## Properties

<div align="left"><figure><img src="/files/UbjE9kSTd9jhceJ5RvxZ" alt="" width="289"><figcaption></figcaption></figure></div>

**Form item name:** This is the name that the **Custom Form** will use to access the output of the checkbox. See [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form) for how it's used.

**Options:** Options for radio button. The **Value** holds the actual value the checkbox takes (that will be able to be used from the output array) and **Label** holds the display name of that checkbox.

**Default value:** Select which option will be the default value.

## Element Style

**Border style:** Toggling this on will create borders around each option.

**Size:** Choose the size of the checkbox. Options include, small, default, and large.

**Disabled:** When toggled on, users will not be able to select an option.

See [Form Check](/app-builder/app-construction/elements/form-check) for data validation.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Output

The output of a checkbox is an **array** of your selections. For example, if you select option2 and option3, the form item will be `[option2.value, option3_value.value]`.&#x20;

## Build interactions

You need to build some interactions to use the output of form elements. Typically, there are two ways to access the output

1. Directly add action after event&#x20;

   After you add an event and an action, use ${event.value} in action to access the output of the element.
2. Use form to collect form data

   See details in [Use Custom Form Container to collect user inputs](/app-builder/popular-use-cases/use-custom-form-container-to-collect-user-inputs)

## Supported Events

**Change Checkbox:** Triggered when a user clicks one of the checkboxes.

## Supported Actions

**Set Value:** Set the output value.

**Set Validate Result:** Set whether the input is valid.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Date Picker

A data picker allows users to select a specific date from a dropdown calendar.

<figure><img src="/files/AhSU3W9eQe9irYMsasnV" alt=""><figcaption></figcaption></figure>

## Properties

<figure><img src="/files/JIaKLG1I4jooTHM1REtB" alt=""><figcaption></figcaption></figure>

**Form item name:** This is the name that the encompassing form will use to access the output of the date picker. See [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form) for how it's used.

**Type:** Choose the date type the user will be selecting. This includes year, month, date, week, and more.

**Default value:** The default value to output if the user does not select a date.

**Max and Min Date:** Select the date range users will be able to choose within.

**Readonly:** When toggled on, users will not be able to select a date.

**Disabled:** When toggled on, users will not be able to select a date.

**Date Format:** Format of the selected date.

**Value Format:** Format that the date will have in the output.

**Range Separator:** Separator character for date ranges.

**Clearable:** When on, users will be able to clear their selection.

**Placeholder:** Placeholder value to display. The element will not take on this value, as opposed to the default value.

**Size:** Choose the size of this element.

See [Form Check](/app-builder/app-construction/elements/form-check) for data validation.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Output

The output format is set by Value format under Property.&#x20;

## Supported Events

**Change Date:** Triggered when a user selects a value.

**Focus:** Triggered when a user selects the Date Picker.

**Blur:** Triggered when a user deselects the Date Picker.

**Visible Change:** Triggered when the Date Picker's dropdown appears/disappears.

## Supported Actions

**Set Value:** Set the output value.

**Set Validate Result:** Set whether the input is valid.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Custom Form

A custom form collects input values from other form elements that can be used to create interactions.

See [Use Custom Form Container to collect user inputs](/app-builder/popular-use-cases/use-custom-form-container-to-collect-user-inputs) for details.

## Configuring the setup

The key is to define the name (form item name) of the value for **inner elements under the form**. This example is an [Input](/app-builder/app-construction/elements/form-elements/input) element contained within a Form. We set the form item name to `email`.

<figure><img src="/files/7yflEouu9IS2MmAegFvn" alt=""><figcaption></figcaption></figure>

## Accessor for form items

When we set up an interaction on the form, we’ll be able to access its item value using `${form.form_item_name}`. In this example, `${form.email}`.

<figure><img src="/files/HQdvYRbbsn3RxH3BmP1P" alt=""><figcaption></figcaption></figure>

## Submitting a form

A form has a supported submit event. However, the submission needs to be triggered by another element.

A form is often used in conjunction with a button, which can trigger a form submit action.

<figure><img src="/files/cQM1EqlOqj9igAQuf2Ha" alt=""><figcaption></figcaption></figure>

## Supported Events

**Submit:** Triggered when the form is submitted.

* An interaction on another element will need to be set up to submit the form. The action should be Element → Form → Submit form.

**Form Invalidate:** Triggered when **Form Check** fails. Refer to [Form Check](/app-builder/app-construction/elements/form-check) for details.

## Supported Actions

**Set form item value:** Set the value of one of the form's items.

**Submit form:** Submit the form (trigger its Submit event).

**Reset form:** Reset form item values.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Input

Input boxes take in simple user input as a string.

<figure><img src="/files/iQh7jtUX6yQuBmIsYuGu" alt=""><figcaption></figcaption></figure>

## Properties

<figure><img src="/files/9Z1WdO2MqVpM3yCNzks5" alt=""><figcaption></figcaption></figure>

**Form item name:** This is the name that the encompassing form will use to access the output of the checkbox. See [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form) for how it's used.

**Input type:** Select the input type that users will be expected to input.

**Default value:** The default value to output if the user does not input anything.

**Max length:** Maximum number of characters a user will be able to input.

**Show word limit:** Show the ratio of characters inputted / total characters allowed.

**Clearable:** Will the user be able to clear their input?

**Input placeholder:** Placeholder text to be displayed. Note that the input will not take on this value, as oppposed to the default value.

**Size:** Select a size for the input element.

See [Form Check](/app-builder/app-construction/elements/form-check) for data validation.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Output

The output of this element is set using Input type in properties.

## Supported Events

**Focus:** Triggered when a user selects the input.

**Blur:** Triggered when a user deselects the input (clicks outside).

**Value input:** Triggered when a user types in the input.

**Value change:** Triggered when a user changes the value of the input and either the input is deselected or users press Enter.

**Press enter:** Triggered when users press Enter when in the input.

## Supported Actions

**Set Value:** Set the output value.

**Get Value:** Get the value of the input.

**Set Validate Result:** Set whether the input is valid.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Multiselect

Multiselect allows you to select multiple options.

<figure><img src="/files/denIa22OB6qXWmsnLVwr" alt=""><figcaption></figcaption></figure>

## Properties

<figure><img src="/files/DtJTNidZH9o8dcwjfMUF" alt=""><figcaption></figcaption></figure>

**Form item name:** This is the name that the encompassing form will use to access the output of the checkbox. See [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form) for how it's used.

**Options:** Each option has 2 input boxes. The upper box holds the actual value the checkbox takes (that will be able to be used from the output array) and the lower box holds the display name of that checkbox.

**Default value:** Select which option will be the default value.

**Multiple limit:** Maximum options a user will be able to select.

See [Form Check](/app-builder/app-construction/elements/form-check) for data validation.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Output

Like checkbox, the output of a multiselect will be an **array**.  For example, if you select option2 and option3, the form item will be `['option2', 'option3']`.&#x20;

## Supported Events

1. Change value: triggered when users change the selection.


# Radio Button

Radio buttons allow users to select one option.

<figure><img src="/files/M9Z3a11MCW7bZs2TLREk" alt=""><figcaption></figcaption></figure>

## Properties

<figure><img src="/files/qWIcpkwc7VkvwHl5lZKi" alt=""><figcaption></figcaption></figure>

**Form item name:** This is the name that the encompassing form will use to access the output of the checkbox. See [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form) for how it's used.

**Options:** Each option has 2 input boxes. The upper box holds the actual value the checkbox takes (that will be able to be used from the output array) and the lower box holds the display name of that checkbox.

**Default value:** Select which option will be the default value.

**Border style:** Toggling this on will create borders around each option.

**Button style:** Change the style. When toggled on, each option will turn into a button.

**Size:** Choose the size of the checkbox. Options include, small, default, and large.

**Disabled:** When toggled on, users will not be able to select an option.

See [Form Check](/app-builder/app-construction/elements/form-check) for data validation.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Output

The output of a radio button is the value of the option that's selected.

## Supported Events

**Select Value:** Triggered when users select an option.

## Supported Actions

**Set Value:** Set the output value.

**Set Validate Result:** Set whether the input is valid.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Radio List

Radio Lists allow users to select one option from a list of options.

![](/files/h8E2NmReZEKrQHB2GBYd)

The first label here (black) represents the formatting when the option is unselected. The second label (blue) represents the formatting when the option is selected.

![](/files/yMLGH4XbjSJyfoUGMUZM)

## Properties

![](/files/yuIO7eR6Cx7oKONUtVwH)

**Form item name:** This is the name that the encompassing form will use to access the output of the checkbox. See [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form) for how it's used.

**Active value:** The value of the default option that will be selected.

**Options:** Each option has 2 input boxes. The upper box holds the actual value the checkbox takes (that will be able to be used from the output array) and the lower box holds the display name of that checkbox.

**Hover with active:** Change color of the option when hovered over.

See [Form Check](/app-builder/app-construction/elements/form-check) for data validation.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Output

The output will be the value of the option that's selected.

## Supported Events

**Change:** Triggered when a user clicks one an option.

**Validate change:** Triggered when the change is validated.

## Supported Actions

**Set Active Value:** Set the output value.

**Set Validate Result:** Set whether the input is valid.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Rich Text Editor

Rich Text Editor is the interface for editing rich text, which presents the user with a "what-you-see-is-what-you-get" editing area.

Rich Text Editor is commonly paired with a [Rich Text](/app-builder/app-construction/elements/web-elements/rich-text) whose input is HTML. Rich Text will be able to display the text that’s entered into the Editor.

<figure><img src="/files/LDlOC38UqW5vnwVVkbDZ" alt=""><figcaption></figcaption></figure>

## Properties

<figure><img src="/files/keGzq3TSxeIebkgNUyjZ" alt=""><figcaption></figcaption></figure>

**Form item name:** This is the name that the encompassing form will use to access the output of the checkbox. See [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form) for how it's used.

**Default value:** Select which option will be the default value.

**Readonly:** When on, user will not be able to input anything.

See [Form Check](/app-builder/app-construction/elements/form-check) for data validation.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

**Text Change:** Triggered when a user changes text in the editor.

## Supported Actions

**Set Rich Text:** Set the input value.

**Set Validate Result:** Set whether the input is valid.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Select

Single selection dropdown.

<figure><img src="/files/lFYbdKUnCJ0M3lvNVO5l" alt=""><figcaption></figcaption></figure>

## Properties

<figure><img src="/files/mv0592NDCmKMAuuVmDLF" alt=""><figcaption></figcaption></figure>

**Form item name:** This is the name that the encompassing form will use to access the output of the checkbox. See [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form) for how it's used.

**Options:** Each option has 2 input boxes. The upper box holds the actual value the checkbox takes (that will be able to be used from the output array) and the lower box holds the display name of that checkbox.

**Default option:** Select which option will be the default value.

**Clearable:** Will the user be able to clear their section?

**Size:** What size will the element be?

**Placeholder:** Placeholder text.

**Disabled:** When disabled, user will not be able to select an option.

See [Form Check](/app-builder/app-construction/elements/form-check) for data validation.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Output

The output of a select element is the value of the option that's been selected.

## Supported Events

**Select Value:** Triggered when a user selects an option.

## Supported Actions

**Set Value:** Set the value of the element.

**Set Validate Result:** Set whether the input is valid.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Switch

A switch element toggles on and off.

<figure><img src="/files/DOyv90RLrdTDgjrKQXh2" alt=""><figcaption></figcaption></figure>

## Properties

![](/files/HWSB417zy0amkwcmLzN5)

**Form item name:** This is the name that the encompassing form will use to access the output of the checkbox. See [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form) for how it's used.

**Mode:** Change between a switch or checkbox display of the element.

**Default value:** Set whether the switch will by default be on or off.

**Active and Inactive text:** Text displayed next to the switch when it is on or off.

**Active and Inactive color:** Color of the active or inactive text.

**Size:** Select a size for the element.

**Disabled:** When toggled on, the user will not be able to change the switch.

See [Form Check](/app-builder/app-construction/elements/form-check) for data validation.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Output

The output of a switch is true/false (boolean).

## Supported Events

**Switch Value:** Triggered when a user switches the value.

## Supported Actions

**Set Value:** Set the value of the element (true/false)

**Set Validate Result:** Set whether the input is valid.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Textarea

Textarea takes in simple user input as a string. It's usually used when you want the user to input a paragraph of text.

<figure><img src="/files/qaMi43rs7ngVK2sBPUSp" alt=""><figcaption></figcaption></figure>

## Properties

<figure><img src="/files/WWoBgmjsDdcNANY31Ejz" alt=""><figcaption></figcaption></figure>

**Form item name:** This is the name that the encompassing form will use to access the output of the checkbox. See [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form) for how it's used.

**Input value:** The default value.

**Textarea rows:** The initial amount of rows for the textarea.

**Min length:** Minimum length of the text in the textarea.

**Max length:** Maximum length of the text in the textarea.

**Auto size:** Enable to let the textarea automatically expand to display more content.

**Show word limit**: Enable to show your Max length in the textarea.

**Textarea placeholder:** Placeholder when there is no text in the teaxtarea.

**Disabled:** Enable to disable the textarea.

See [Form Check](/app-builder/app-construction/elements/form-check) for data validation.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

**Focus:** Triggered when a user selects the Textarea.

**Blur:** Triggered when a user deselects the Textarea (clicks outside).

**Value input:** Triggered when a user types in the Textarea.

**Value change:** Triggered when a user changes the value of the Textarea and either the Textarea is deselected or users press Enter.

**Press enter:** Triggered when users press Enter when in the Textarea.

## Supported Actions

**Set Value:** Set the value of the element.

**Set Validate Result:** Set whether the input is valid.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Upload

You can add an Upload element in your data app for your end users to upload files. The files end users uploaded will be saved in your media files in Resources. You can then load the files to databases, or use them in machine learning use cases.

<figure><img src="/files/La2E1JJxEru3fhinuOGy" alt=""><figcaption></figcaption></figure>

## Properties

**Form item name:** This is the name that the encompassing form will use to access the output of the checkbox. See [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form) for how it's used.

**Path:** Select the directory path where the uploaded files will be stored in media folders.&#x20;

**Public URL:** This property specifies the public URL where the uploaded files can be accessed. It is essential for retrieving and displaying the files to end users.

**Multiple:** Whether or not allow user to upload multiple files.

**Allow extensions:** This property determines which file types are allowed for upload. Extensions should be listed and separated by commas, e.g., <mark style="color:red;">`png,jpeg,gif`</mark>.

**Max File Size:** This defines the maximum size for uploaded files, measured in kilobytes (KB). Setting this to 0 may allow files of any size, depending on server configurations.

## Example: Load User uploaded CSV files to PostgreSQL

Combining Upload and the Load CSV To Postgres API, you can build service for users to upload csv and preview them. This example serves as one of our template **Upload CSV template,** which you can find in the app builder.

1. Add An Upload element
2. Select event **Upload Successfully**
3. (Optional) Use Generate Unique ID to get a table name and save it in app data
4. Add the "Load CSV To Postgres" action. Use the path of the first uploaded file as the `Path` parameter.
5. (Optional) Add a "Set Text" action to display a message indicating whether the operation was successful.

<figure><img src="/files/xcGLe9kCCfYRoihbGJXo" alt=""><figcaption></figcaption></figure>


# Web Elements

These elements are basic web elements, generally used for navigational or informational purposes.

{% content-ref url="/pages/uYpWo9BLOxh2CA66FuWg" %}
[Badge](/app-builder/app-construction/elements/web-elements/badge)
{% endcontent-ref %}

{% content-ref url="/pages/uYww9DL1MHycl8zTC7l5" %}
[Button](/app-builder/app-construction/elements/web-elements/button)
{% endcontent-ref %}

{% content-ref url="/pages/GtOdI8nXAyuAYiUXGTJ2" %}
[Chart](/app-builder/app-construction/elements/table-and-chart/chart)
{% endcontent-ref %}

{% content-ref url="/pages/F0NQ0RkAghHMUKXnBM0A" %}
[Clickable](/app-builder/app-construction/elements/web-elements/clickable)
{% endcontent-ref %}

{% content-ref url="/pages/6uS2dHiHolb9ocMNVvGF" %}
[Code Block](/app-builder/app-construction/elements/advanced-elements/code-block)
{% endcontent-ref %}

{% content-ref url="/pages/5DBJZVcVMHu5JvoIuUwl" %}
[Collapse Menu](/app-builder/app-construction/elements/web-elements/collapse-menu)
{% endcontent-ref %}

{% content-ref url="/pages/k68aUWiBtesIW556zWGD" %}
[Condition](/app-builder/app-construction/elements/advanced-elements/condition)
{% endcontent-ref %}

{% content-ref url="/pages/M7mJkMm7cU7AmkwAxRqt" %}
[Divider](/app-builder/app-construction/elements/web-elements/divider)
{% endcontent-ref %}

{% content-ref url="/pages/AiYKa1wKGnUZI3WPKX2I" %}
[Icon](/app-builder/app-construction/elements/web-elements/icon)
{% endcontent-ref %}

{% content-ref url="/pages/vb0heucW4iQFREgMrTIm" %}
[Image](/app-builder/app-construction/elements/web-elements/image)
{% endcontent-ref %}

{% content-ref url="/pages/AK8QNo4TeThfqh5lOaMe" %}
[Link](/app-builder/app-construction/elements/web-elements/link)
{% endcontent-ref %}

{% content-ref url="/pages/anSNwATX1mlgvXgrq2s0" %}
[Message](/app-builder/app-construction/elements/web-elements/message)
{% endcontent-ref %}

{% content-ref url="/pages/NXGqycCAl48ViacykXd9" %}
[Notification](/app-builder/app-construction/elements/web-elements/notification)
{% endcontent-ref %}

{% content-ref url="/pages/fCIeLUcATS4FpZASrmUv" %}
[Pagination](/app-builder/app-construction/elements/web-elements/pagination)
{% endcontent-ref %}

{% content-ref url="/pages/aXuwmRxua2gqadqjt7p8" %}
[Popover](/app-builder/app-construction/elements/web-elements/popover)
{% endcontent-ref %}

{% content-ref url="/pages/9aVIUvwdwY7DbsSlOC4K" %}
[Rate](/app-builder/app-construction/elements/web-elements/rate)
{% endcontent-ref %}

{% content-ref url="/pages/pSrDa8C0oJO5lB1yY3Q4" %}
[Rich Text](/app-builder/app-construction/elements/web-elements/rich-text)
{% endcontent-ref %}

{% content-ref url="/pages/Ocz0m6djdAs0tit5sChq" %}
[Search Bar](/app-builder/app-construction/elements/form-elements/search-bar)
{% endcontent-ref %}

{% content-ref url="/pages/3wc9fO9mRANdPBztrd8i" %}
[Table](/app-builder/app-construction/elements/table-and-chart/table)
{% endcontent-ref %}

{% content-ref url="/pages/fN8SoIz6RtBr9F9zhbJe" %}
[Tabs](/app-builder/app-construction/elements/web-elements/tabs)
{% endcontent-ref %}

{% content-ref url="/pages/BopN1fOHGA7YcU2H0pV2" %}
[Text](/app-builder/app-construction/elements/web-elements/text)
{% endcontent-ref %}


# Badge

A number or status mark over an element. Badges are typically used for buttons or icons.

By default, a badge has 2 parts:&#x20;

1. A section to insert another element.
2. The badge indicator, which is a red [Text](/app-builder/app-construction/elements/web-elements/text) element.

<figure><img src="/files/3utWG0X0l2ZpF3BxALUU" alt=""><figcaption></figcaption></figure>

For example, this is what it will look like when you drag a button into a badge element.

<figure><img src="/files/tEWloVrPQA6Iq933xjkQ" alt=""><figcaption></figcaption></figure>

## Properties

No properties. See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

No supported events.

## Supported Actions

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Button

A button is a clickable element.

<figure><img src="/files/NhepjMmsxiw6Laj44vYd" alt=""><figcaption></figcaption></figure>

## Properties

<figure><img src="/files/cL9uIlTeiyUSrQCBDODE" alt=""><figcaption></figcaption></figure>

**Button text:** Displayed text on the button.

**Button size:** Change the button size. Options include the default size, large, and small. If you'd like to further customize the size, see [Size](/app-builder/app-construction/elements/css-styles/size).

**Disabled:** When switched on, the button will not be clickable

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

**Click Button:** Triggered when a user clicks on the button.

## Supported Actions

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Clickable

For elements that do not have click events, they can be wrapped with a clickable. which effectively turns it into a button.

By default, a clickable is an empty container into which you can drag other elements.

<figure><img src="/files/8ggFq4CsdRdnEqj1Fh3f" alt=""><figcaption></figcaption></figure>

## Properties

<figure><img src="/files/TGawUs0KJiRFrAF4D4FH" alt=""><figcaption></figcaption></figure>

**Hover color:** Background color when mouse hovers over the clickable.

**On Hover color:** Color of text in the clickable when hovered over.

**On Active color:** Color of text in the clickable as it is being clicked.

**Animate Color:** Length of animation in milliseconds.

**Text:** Displayed text. Note that once an element is dragged into the clickable, the text will no longer be visible.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

**Click Element:** Triggered when a user clicks on the element(s) in the clickable.

## Supported Actions

**Set Text:** Set text property of the clickable.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Collapse Menu

Collapse menus are typically used for navigation to different pages or sections.

A collapse menu contains 3 parts:

1. Title container
2. Arrow icon to collapse and expand the menu (on the right)
3. Menu content

<figure><img src="/files/QBupiDwUfDbVktCYKUTT" alt=""><figcaption></figcaption></figure>

You can customize all three parts. For example, in menu content, you can add a [Clickable](/app-builder/app-construction/elements/web-elements/clickable) with [Text](/app-builder/app-construction/elements/web-elements/text) inside, and set an interaction on the clickable to navigate to a different page.

## Properties

<figure><img src="/files/fsGu3yM4CtY61B5wxASO" alt=""><figcaption></figcaption></figure>

**Group ID:** If you have multiple collapse menus, group them together by Group ID. To group elements, give them the same ID.

**Single Collapse:** If you have grouped collapsed menus by Group ID, turning on Single Collapse ensures that only one collapse menu will be open at a time.

**Default Expand:** When on, the collapse menu will be expanded by default.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

**Toggle menu:** Triggered when user toggles the menu arrow.

## Supported Actions

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Divider

A dividing line to separate content.

## Properties

<figure><img src="/files/Z57fZnC7hXicreUypq7g" alt=""><figcaption></figcaption></figure>

**Content:** Text to display in the divider.

**Set divider's direction:** Orient the divider horizontally or vertically

**Set the style:** Choose a solid or dotted divider.

**Set the position of content:** Align the divider's content to the left, right, or center.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

No supported events.

## Supported Actions

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Icon

An icon is a representative image or symbol.

## Properties

<figure><img src="/files/lyN7e3AVx9zDlFSGInyf" alt=""><figcaption></figcaption></figure>

**Icon type:** Select an icon from the dropdown.

For customized icons, click on the code editor toggle and paste in the SVG path.

<figure><img src="/files/qJmJ1qjj4PISR4BwhWJs" alt=""><figcaption></figcaption></figure>

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

**Click Icon:** Triggered when a user clicks on the icon.

## Supported Actions

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Image

The Image element can be used to display images.

## Properties

![](/files/yQvc5r4JJTLEewel83Ia)

**Image URL:** URL to the image you'd like to display.

**Alternate description:** Written description of the image to be display if the image fails to load.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

No supported events.

## Supported Actions

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Link

Use a link to add a hyperlink to elements, most often text. Insert another element into a link element.

## Properties

<figure><img src="/files/yNx7cy0kA5be62emsEZB" alt=""><figcaption></figcaption></figure>

**URL:** The URL to navigate to when the link is clicked.

**Open in a new tab:** When toggled on, the page will open in a new tab. When off, it will open in the same tab.

**Visited color:** Color of the link once it's been clicked on.

**Hover color:** Color of the link when a user hovers over it

**Active color:** Color of the link as it's being clicked.

**Link color:** Color of the link.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

No supported events.

## Supported Actions

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Message

A message is a popup that can be displayed at the top of your page.

Once you’ve added your message element, click “Edit Message”.

Often, you need to add interactions to manage opening and closing message.

<figure><img src="/files/mhe8L0wuvrsDNv3JIccs" alt=""><figcaption></figcaption></figure>

A popup area will appear. Next, drag in other elements, such as text, to build your message.

## Properties

<figure><img src="/files/9zRVLHTNQSOIa0QrQqCr" alt=""><figcaption></figcaption></figure>

**Type:** Select a message type. This option styles your message's background color based on the colors set in your theme. Options include: success, warning, info, error, or custom.

**Duration:** Specify how long the message will be displayed on the screen.

**Offset top:** Set the distance (in pixels) from the top edge of the screen.

**Show close icon:** When toggled on, users will be able to close the message manually.

**Z-index:** Set the z-index of the message. It is used to ensure that the modal is displayed on top. See [CSS doc](https://developer.mozilla.org/en-US/docs/Web/CSS/z-index) for more details.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Displaying a message

To trigger the message popup, set up an interaction on another element, such as a button.

Here is an example for a button click to trigger the message popup.

<figure><img src="/files/lBopeszNr5ul4sTwr2hH" alt=""><figcaption><p>Use interaction to show a message</p></figcaption></figure>

## Supported Events

**Close Message:** Triggered when a user closes the message.

## Supported Actions

**Show Message:** Display message on the screen.

**Close Message:** Close message.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Modal

A modal is a popup that can be displayed in the center of your page.

Once you’ve added your modal element, click “Edit Modal” to open up the popup area to build the contents.

Usually, you need to add [interactions](/app-builder/app-construction/interactions) to open and close model, see [#displaying-a-modal](#displaying-a-modal "mention")

<figure><img src="/files/mNaOYyQtdX5mOQT2DiZl" alt=""><figcaption></figcaption></figure>

## Properties

![](/files/dc11qO7JToxcqOnpdfzH)

**z-index:** Set the z-order (stack order) of a positioned element. It is used to make sure the modal is displayed on top.

**Show mask:** Determines whether you want to darken the page when the modal is open.

**Show dismiss button:** Display the close button at the top right of the modal.

**Close modal after clicking on mask:** Enable this option to close the modal when a user clicks outside of it.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Displaying a modal

To trigger the modal to open, set up an [interaction](/app-builder/app-construction/interactions) on another element, such as a button.

Here is an example for a button click to trigger the modal to open.

<figure><img src="/files/Qnze1wft3tZYslD6MpLr" alt=""><figcaption></figcaption></figure>

## Supported Events

**Open Modal:** Triggered when a user opens the modal.

**Close Modal:** Triggered when a user closes the modal.

## Supported Actions

**Open Modal:** Display modal on the screen.

**Close Modal:** Close modal.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Notification

Notification displays a global notification message at the corner of the page.

<figure><img src="/files/wsMSkqKq2VWxLZtvRAEE" alt=""><figcaption></figcaption></figure>

Similar to a [Message](/app-builder/app-construction/elements/web-elements/message), you can customize the notification by clicking on "Edit Notification". You will also need an interaction to trigger the notification to open.

<figure><img src="/files/Eu4yKCovSBDEGNWxORGu" alt=""><figcaption></figcaption></figure>

## Properties

![](/files/V260gUEGPls4dZm1ZP05)

**Position:** Choose to display the message on the top-right, top-left, bottom-right, or bottom-left of the screen

**Duration:** How long the notification will be displayed on the screen

**Offset top:** Offset from the top edge of the screen in pixels.

**Show close icon:** When toggled on, users will be able to close the message manually.

**Z-index:** Set the z-index of the message. See [CSS doc](https://developer.mozilla.org/en-US/docs/Web/CSS/z-index) for more.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

**Click Notification:** Triggered when a user clicks on the notification.

**Close Notification:** Triggered when a user closes the notification.

## Supported Actions

**Show Notification:** Display notification on the screen.

**Close Notification:** Close notification.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Pagination

The Pagination element is used to provides a way for users to navigate through these pages and access the content by page number.

## Properties

**Page**: Indicates the current page that the user is on.

**Page Size**: Indicates the number of items displayed on each page.

**Pager count**: number of pagers. Pagination collapses when the total page count exceeds this value

**Total Pages**: Indicates the total number of pages available for the content.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.


# Popover

A popover is like a pop-up box that appears when the user clicks on an element, providing additional information.

<figure><img src="/files/FokF0ZvtZvR1ixr1MZrN" alt=""><figcaption></figcaption></figure>

There are 2 parts to a Popover element:

1. The trigger element
2. The pop-up element

<figure><img src="/files/RfJAALfd27SFHi1Diker" alt=""><figcaption></figcaption></figure>

Insert the trigger element where it says “Drop element here”.

To edit the content in the popout menu, click the “change view mode” button. Then drop elements into the white box below.

## Properties

<figure><img src="/files/okulZ5qaszq20qJCIsUh" alt=""><figcaption></figcaption></figure>

**Trigger:** Define how the popover will be triggered.

* Click: Open when user clicks on the trigger element.
* Hover: Open when user hovers over the trigger element.
* Contextmenu: Open when a user right clicks.
* Event: Open when another element prompts it to through an interaction.

**Placement:** Where the popover will appear, relative to the trigger element.

**Disabled:** When on, the popover will be disabled and cannot be triggered.

**Show arrow:** When on, the arrow on the popover box will appear.

**Arrow background:** Choose color for the arrow.

**ShowAfter time:** Delay of appearance in milliseconds.

**HideAfter time:** Delay of disappearance in milliseconds.

**AutoClose time:** Timeout to hide tooltip in milliseconds.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

No supported events.

## Supported Actions

**Set Visible:** Open popover.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Rate

The rate element shows star rating scores. Rate divides rating scores into several levels and these levels can be distinguished by using different background colors.

<figure><img src="/files/GD8p6jDWxF8kUWUGtH1c" alt=""><figcaption></figcaption></figure>

You can change the icons to your desired shape by clicking on the [Icon](/app-builder/app-construction/elements/web-elements/icon) within the rate element and altering its type.&#x20;

* Changing the first (yellow) icon will set the style of the icons which show the selected rating.&#x20;
* Changing the second (gray) icon will set the style of the icons which show the maximum rating.
* i.e. if the selected rating is 3 out of 5, the page will display 3 icons of the first style followed by 2 icons of the second style.

## Properties

<figure><img src="/files/gcW9Y69qgEeXck4BqFV7" alt=""><figcaption></figcaption></figure>

**Max Score:** Set the maximum rating

**Default Score:** Set what rating is shown by default

**Allow Half:** Toggle whether user can set a half rating

**Clearable:** Toggle whether user can clear the rating once its set

**Disabled:** Toggle to disable rating element

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

**Change:** Triggered when a user changes the rating.

## Supported Actions

**Set Score Value:** Set the value of the score.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Rich Text

Rich text displays text that’s formatted with standard formatting options, such as bold and italics, that are unavailable with plain text. The input value of Rich Text is HTML.

Rich Text is commonly paired with a [Rich Text Editor](/app-builder/app-construction/elements/form-elements/rich-text-editor) whose output is HTML. Rich Text will be able to display the text that’s entered into the Editor.

## Properties

![](/files/T9N3DQunEgWAf0unj0Ss)

**Default value:** HTML text to display. You can use the rich text editor here, or use the \</> code block to enter raw HTML.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Example

This is a piece of html, down below shows the difference between text element and rich text element.

```html
<p>Hi there&nbsp;<img src="https://a.slack-edge.com/production-standard-emoji-assets/14.0/apple-medium/1f44b.png">, glad that you found us!</p>
```

![](/files/YRRXUPzxhZ6qtb7ddIqM)

{% hint style="info" %}
Using rich text along with rich text editor together, see tutorial[Rich text and rich text editor](/app-builder/popular-use-cases/rich-text-and-rich-text-editor)&#x20;
{% endhint %}

## Supported Events

No supported events.

## Supported Actions

**Set Rich Text:** Set the HTML text to display.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Tabs

The tabs element allows you to display content under various views which can be selected by the user. The first label here (blue) represents the formatting when the option is selected.&#x20;

<figure><img src="/files/CAZGCqC0HzUl1eJ1AkrS" alt=""><figcaption></figcaption></figure>

Quick add a new tab by clicking the + sign on the right side.

You can edit the content under each tab by dragging elements into the blue slot.

## **Properties**

To configure the tab, navigate to Config → Property. Under Tab Options, you’ll see a pair of inputs for each tab. The upper input is the actual value that tab takes on, and the lower is the display value.

<figure><img src="/files/h3HmcYOrNQ9OqR9jZaOX" alt=""><figcaption></figcaption></figure>

**Tab options:** Each tab has a pair of input boxes.

1. Enter the value of the tab in the first input box.&#x20;
2. Enter the display name of the tab into the second input box.

Add additional tabs with “+ Add an item”.

**Default tab:** The value of the default tab to display.

**Type:** Choose a style type. Options include the default, card, or border-card.

**Position:** Position the tabs at the top, right, bottom, or left of the element.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Supported Events

No supported events.

## Supported Actions

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Text

The Text element allows you to display simple text.

Either double click the element or go to properties to change the text.

## Properties

![](/files/JPFaJvFvOIN6ppPFnQnD)

**Text:** Text to display.

**Show only one line:** When toggled on, the element will only display the first line of text. The rest will be hidden.

**Text type:** The default type is Paragraph. You can change the text type to Heading 1, Heading 2, Heading 3, Heading 4, or Span.

## Supported Events

No supported events.

## Supported Actions

**Set Text:** Set text to display.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Layout Elements

These elements help with arranging and organizing your page.

{% content-ref url="/pages/tXObQuvsBq2lxyFIWHzn" %}
[Container](/app-builder/app-construction/elements/layout-elements/container)
{% endcontent-ref %}

{% content-ref url="/pages/XJFjZHxdGlqXZO2abIpr" %}
[List](/app-builder/app-construction/elements/layout-elements/list)
{% endcontent-ref %}

{% content-ref url="/pages/8GaN2BWvR12DHPdCrSL2" %}
[Print](/app-builder/app-construction/elements/advanced-elements/print)
{% endcontent-ref %}


# Container

Containers are used to wrap and pad other elements. They can be used to group elements and organize an app’s layout.

If you navigate to Config → Styles, you’ll be able to configure the container’s layout, spacing, etc.

* `Display:inline` will arrange container content vertically while `Display:flex` will allow you to place items next to each other, horizontally.
* Justify affects how content is arranged from left to right.
* Align affects how content is arranged from top to bottom.
* Wrap options specify how the container will deal with overflow.

<figure><img src="/files/E44MHZCOj66u0LywleBG" alt=""><figcaption></figcaption></figure>

## Supported Events

No supported events.

## Supported Actions

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# List

List is used to render each item from an array of data. Each item in the list shares the same layout structure, but renders distinct data from the array item.

<figure><img src="/files/6Qb1k3kS5uRuRijuUUgm" alt=""><figcaption><p>Example of a list of integrations</p></figcaption></figure>

## Sending data to a list

There are 3 main ways to send data to a list: selecting a data node, setting element data, or through an interaction.

1. In properties, you can select a data node to use for the list.

   <figure><img src="/files/HHmlSLgpWlYJ5togZxV0" alt=""><figcaption></figcaption></figure>
2. The array can be set in the Data tab on the left panel.\
   ![](/files/PlWkVdLu2LuO4oaq2eoj)
3. You can also send data through an interaction. In this example, the array `[1,2,3]` will be sent to the list when a button is clicked.

   <figure><img src="/files/iSaSXPDmvg2K6luKyBY2" alt=""><figcaption></figcaption></figure>

## Displaying data in the list

Let’s say the list data was `[”a”,”b”,”c”]`.

To access the list’s data, you can use `$item` (the item data), `$index` (the item index of the list), and `$list` (the array).

Here, there is a button, text, and divider element added to a list.

<figure><img src="/files/rYPdh8etPXeYgEUuyYwL" alt=""><figcaption></figcaption></figure>

This is how the list would look in production.

<figure><img src="/files/GUKvMULc9xq8QP8rKYkP" alt=""><figcaption></figcaption></figure>

## What to display when there’s no data

You can customize the content for when the list data is empty.

Hover over the Change View Mode arrow and select empty. Then you’ll be able to drag in elements to build the empty view.

<figure><img src="/files/nF9bUgQ120iUHaz3Exc9" alt=""><figcaption></figcaption></figure>

## Supported Events

No supported events.

## Supported Actions

**Set List Data:** Set data to use for the list.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Advanced elements


# Code Block

The code block element in Acho App Builder uses JavaScript to build web components. It can receive data from external sources through the Data object property, which is stored in `data` once received. For a step-by-step guide, please refer to [Create a Chart with Code Block and D3 Library](/app-builder/popular-use-cases/create-a-chart-with-code-block-and-d3-library)

## Properties

<div align="left"><figure><img src="/files/NX4neCOaKvUDY0vbXNwO" alt="" width="284"><figcaption><p>Code Block Properties</p></figcaption></figure></div>

**Code:** This property is used to store the user's code. By default, the code contains a setupCode function that returns a render function responsible for rendering HTML on the page.&#x20;

**Data object:** This property is passed to the `render` function, allowing the code to access data from the app. It can be accessed directly within the `render` function by using the name `data`.

* **Example**: Access a Page data using **Data object**

  The data is displayed by console.log(data) in **Code block**.

  <img src="/files/0FFP7sITArutrB2EpDCu" alt="" data-size="original">

  <img src="/files/t6FPSjTGf3UT2jkilUrD" alt="" data-size="original">

**Run on mount:** The code will run right after the code block shown on the page. You can turn this off and call the render function in action manually.

**Rerender on resize:** When the window or container resizes, rerun the render function so the web component size fits the window/container.

**Rerender on data change:** When the data object changes, rerun the render function. This keeps the web component synced to the data.

## Supported Events

**Code Block** support only custom events, which allows you to customize the behavior of the code block and interact with other elements in the app. To add an event to the code block element, you can use the `defineEvent` function.&#x20;

The defineEvent function below is used to define a "Click" event for the code block. It takes an event definition object that specifies the event's title, name, and payload structure. In this case, the payload includes "Product" and "Value" fields with their corresponding types.

```
defineEvent(/* event definition */ {
        title: "Click",
        name: "click",
        payload: [
            {
                name: "Product",
                field: "product",
                type: "string"
            },
            {
                name: "Value",
                field: "value",
                type: "number"
            }
        ]
    })
```

To trigger the custom event within the code block, you can use the emit function. Here's an example:

```
emit('click', { product: name, value: data});
```

In this code snippet, the emit function is used to trigger the "Click" event with the payload { "product": name, "value": data }. When this line of code runs, the "Click" event will be triggered with the specified payload. Please note that you need to replace `name` and `data` with the actual values you want to pass as the payload when triggering the event.

## Supported Actions

**Render:** Run the render function.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Condition

Condition elements show users different views based on defined conditions.

To switch views, click on the dropdown on the top right.

To set the content for a view, click on a tab to build the view page.

<figure><img src="/files/EjD5B5CFFcAhyGL4XhS2" alt=""><figcaption></figcaption></figure>

## Properties

<img src="/files/B5Frkje8I8SQ3XTCR2Ki" alt="" data-size="original">

**Conditional View List:** Each view has a pair of input boxes.

1. Enter the view name into the first input box.&#x20;
2. Enter the condition into the second input box.

Add additional views with “+ Add an item”.

See [Tooltip](/app-builder/app-construction/elements/tooltip) for tooltip configurations.

## Example

In this example, there are two views, ‘Display Details’ and ‘No Data’.

<figure><img src="/files/ba67qEggl7G1J3mAqzx6" alt=""><figcaption></figcaption></figure>

When the value of app data variable `display_details` is  `“false”`, the condition element displays the ‘No Data’ view. When it is `"true"`, the condition element will display the ‘Display Details’ view.

See [Data Store](/app-builder/app-construction/data-store) for more about accessing app data.

## Supported Events

No supported events.

## Supported Actions

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# Print

The Print Container is for setting contents to be printed. Our [Invoice Generator](https://publish.acho.io/441) is a great use case for the Print Container. Each Print Container represents a single page you want to print.

![](/files/rNKfGFoCmV3p0D2M7L9J)

<figure><img src="/files/FsMXQ3aGtCjjGrLosTbo" alt=""><figcaption></figcaption></figure>

A trigger is needed for the printing. In the following example, we used a button to trigger the "Print page" event of the Print Container. Everything in the Print Container will be printed.&#x20;

<figure><img src="/files/VkvxB3bNLjPVEN9NBIWD" alt=""><figcaption></figcaption></figure>

## Supported Events

No supported events.

## Supported Actions

**Print Page:** Print contents of the print container.

**Set Data:** Change element data. See [Data Store](/app-builder/app-construction/data-store).

**Set Loading:** Set loading animation. See [Set loading animations](/app-builder/popular-use-cases/set-loading-animations).

{% hint style="info" %}
Visit [Interactions](/app-builder/app-construction/interactions) for more on events and actions.
{% endhint %}


# CSS Styles

Elements styles and layouts

Acho app builder's elements follow CSS style. Wich CSS knowledge, you can arrange elements freely and customize their size, margin, color to fit your desired design style.

Detailed descriptions of each element's style are presented as follows:

{% content-ref url="/pages/7SN7u2KMlOnslse6E1VC" %}
[General techniques](/app-builder/app-construction/elements/css-styles/general-techniques)
{% endcontent-ref %}

{% content-ref url="/pages/kW7qH1ZpoTrcay0J46nT" %}
[Layout](/app-builder/app-construction/elements/css-styles/layout)
{% endcontent-ref %}

{% content-ref url="/pages/FPgfdzZIUGwajl4tuChD" %}
[Spacing](/app-builder/app-construction/elements/css-styles/spacing)
{% endcontent-ref %}

{% content-ref url="/pages/CW8n1RyR99tSJUgn20jM" %}
[Size](/app-builder/app-construction/elements/css-styles/size)
{% endcontent-ref %}

{% content-ref url="/pages/0ix9EC6kxK5wRyv1thyz" %}
[Position](/app-builder/app-construction/elements/css-styles/position)
{% endcontent-ref %}

{% content-ref url="/pages/SIeNcndg1Oz7poFSfBzo" %}
[Typography](/app-builder/app-construction/elements/css-styles/typography)
{% endcontent-ref %}

{% content-ref url="/pages/RvS4ZhjkACUN5zzappEj" %}
[Background](/app-builder/app-construction/elements/css-styles/background)
{% endcontent-ref %}

{% content-ref url="/pages/hBiXwAYMKbSJjq3U6SP5" %}
[Border](/app-builder/app-construction/elements/css-styles/border)
{% endcontent-ref %}

{% content-ref url="/pages/Yyk7a8xF3wsihAJnYpgY" %}
[Effect](/app-builder/app-construction/elements/css-styles/effect)
{% endcontent-ref %}


# General techniques

## Conditional formatting

You can use the expression below to achieve conditional formatting. It is very similar to conditional expression, or ternary operator.

<mark style="color:green;">`${`</mark>`condition && exprIfTrue || exprIfFlase`<mark style="color:green;">`}`</mark>

The `${}` notation is an [accessor](/app-builder/app-construction/accessors) that allows you to access data in your code. Inside the `${}`, the conditional operator manages the conditional operation.

For example, if you want to set a font color to red if a certain condition is true, and black if it is false, you can use the expression like this:

<mark style="color:green;">`${`</mark>` ``isConditionTrue && "Red" || "Black"`<mark style="color:green;">`}`</mark>

In this example, if the variable `isConditionTrue` is true, the expression will evaluate to "Red". If it is false, it will evaluate to "Black".

## Basic Calculating in CSS styles

1. Using `calc()` :\
   `calc()` is a built-in CSS function that allows you to perform simple arithmetic calculations on CSS property values. It works with various units like pixels, percentages, ems, rems, and more.<br>

   Here's an example of how you can use `calc()` to calculate the width of an element as 100 pixel plus 20% of its parent element's width:

   ```css
   calc(100px + 20%);
   ```
2. Using [accessor](/app-builder/app-construction/accessors) :

   If you need to perform more complex calculations that are not possible with `calc()`, you can use JavaScript expressions inside CSS. To do this, you can use the `${}` syntax in a template literal.

   Here's an example of how you can use a JavaScript expression to set the element size&#x20;

   ```css
   ${960-2*30}px;
   ```

   This will evaluate the JavaScript expression `960-2*30` to `900`, and then append the "px" unit to the end, resulting in size of 900 pixels.\
   \
   Further more, you can conbine other data with it together. You may add custom variables in Data and use them here.

   ```css
   ${#page.custom_width-2*#page.custom_margin}px;
   ```

   This will evaluate  `#page.custom_width-2*#page.custom_margin`, and then append the "px" unit to the end. By using custom variables like this, you can easily change the CSS properties of a set of elements together by modifying the values of your data.

## Interactive styling example

Here is a example to use the techniques above to highlight number of interest.

1. Create data node

   &#x20; ![](/files/vMxxXTLXeK52L3Pzkbu2)
2. Create a list element and drag a text element inside, set text to ${$item.n}
3. Create a page variable called number in Data Store
4. Create a input element to set page variable
   1. Set Config -> Property -> Input type to 'number'
   2. Add interactions, attention: Set Action Parameters as the image do.

      <figure><img src="/files/Lk8UTuMlxBtQZasOhCnQ" alt=""><figcaption></figcaption></figure>
5. Set text element styles parameters
   1. set width and height to 64px
   2. set background color to `${$item.n==#page.number&&'red'||'green'}`
6. Click 'Preview' to see the final result. Enter any number between 1 to 10 in the input to activate highlight number.<br>

   <figure><img src="/files/6ru38ewKeCcsTNHZrT5z" alt=""><figcaption></figcaption></figure>


# Layout

## Display

`Display` is a property that specifies the type of layout a certain HTML element should have. The display property is a crucial aspect of web design, as it determines how an element is positioned and laid out on a web page. The value of the display property can be set to either ![](/files/zj0nNBYLpNZYkTsqS9sb)`Inline`, ![](/files/B47uQKXjYzMExoyUjRmL)`inline-block`, ![](/files/KJgBoUjcIg9SVFTxaA0B)`block`, ![](/files/9OvVTsd4CAZZDDLiNrGs)`none`, and ![](/files/By52a3MIRVs8VO4sv0zt)`flex` are different display values for HTML elements. In practical use with Acho App builder, ![](/files/By52a3MIRVs8VO4sv0zt)`flex` is the most powerful and often used one.&#x20;

* ![](/files/zj0nNBYLpNZYkTsqS9sb)`Inline`  elements only occupy as much space as their content and do not cause a new line to start. Examples of inline elements include spans, links, and images.&#x20;
* ![](/files/By52a3MIRVs8VO4sv0zt)`Flex` elements define a flex container and allow direct children to be laid out in a flexible way, either in a row or a column. This display value is useful for creating responsive layouts that can adjust to different screen sizes and devices.
* ![](/files/KJgBoUjcIg9SVFTxaA0B)`Block` elements occupy the full width of their parent container and create a new block formatting context. This means that they start on a new line and stack vertically, one after the other. Examples of block elements include headings, paragraphs, and divs.
* ![](/files/B47uQKXjYzMExoyUjRmL)`Inline-block` elements are similar to inline elements, but they can have a specified width and height and can be treated as a block element for formatting purposes.
* ![](/files/9OvVTsd4CAZZDDLiNrGs)`None` elements do not appear on the page and do not take up any space.

## Direction

The `Direction` property **only** works when the `display` property is set to `flex`.

The `Direction` property is used to establish the main-axis of a flex container and define the direction that the flex items are placed in the container. There are four possible values for `Direction`: ![](/files/9DlVbbLKlqwBACBrE4KF)`row`, ![](/files/calk1451k4FfRwhelTtA)`row-reverse`, ![](/files/suOuM7ejI08X5VI86oMb)`column`, and ![](/files/ezZYtUGTWtjcnj765PBm)`column-reverse`.&#x20;

* The default value is ![](/files/9DlVbbLKlqwBACBrE4KF)`row`, which means that the flex items are arranged left-to-right. ![](/files/9DlVbbLKlqwBACBrE4KF)`row-reverse` is the opposite.
* ![](/files/suOuM7ejI08X5VI86oMb)`column` and ![](/files/ezZYtUGTWtjcnj765PBm)`column-reverse` work similarly, but they arrange the items in a top-to-bottom direction. ![](/files/suOuM7ejI08X5VI86oMb)`column` places the items from the top of the container to the bottom, while ![](/files/ezZYtUGTWtjcnj765PBm)`column-reverse` places the items from the bottom to the top.

## Justify

The `justify-content` property **only** works when the `display` property is set to `flex`. It is used to align the flex items along the main axis within a flex container. When only `display: flex` is set, `justify-content` becomes applicable. The property takes the following values:&#x20;

* ![](/files/Mv8tiFx6R8Au0akBM3Q9)`flex-start` (default): items are packed towards the start of the main axis.
* ![](/files/33FVnR6GrJ0XvGXcQ496)`flex-end`: items are packed towards the end of the main axis.
* ![](/files/Sk1ITV5JGvQ5mXqLTwlF)`center`: items are centered along the main axis.
* ![](/files/vsyGvsO8taMnxjGZ5MDE)`space-between`: items are evenly distributed along the main axis, with the first item at the start and the last item at the end.
* ![](/files/nFsvBy2N5CYMYk54Wt6b)`space-around`: items are evenly distributed along the main axis with equal space around them.

## Align

The `align-items` property **only** works when the `display` property is set to `flex`. It is used to align the flex items along the cross axis within a flex container. The values for `align-items` are:&#x20;

* ![](/files/DGo3XzcjDgacUjne5Ibr)`flex-start`: items are aligned at the start of the cross axis.
* ![](/files/HJZLpId25INJj0OKPcOO)`flex-end`: items are aligned at the end of the cross axis.
* ![](/files/anXkH0PcgymnBQagnjNB)`center`: items are centered along the cross axis.
* ![](/files/I6t6BCgnT5eAGBh2029U)`baseline`: items are aligned such that their baselines align.
* ![](/files/qE1aRkwrQWbKUkBs1Oxt)`stretch` (default): items are stretched to fill the container along the cross axis.

## Flex wrap

The `flex-wrap` property is used to control how flex items are wrapped within a flex container.

The `flex-wrap` property has three possible values: `nowrap`, `wrap`, and `wrap-reverse`.

* `nowrap` (default): all flex items will be on one line.
* `wrap`: flex items will wrap onto multiple lines, from top to bottom.
* `wrap-reverse`: flex items will wrap onto multiple lines from bottom to top.

## Grow

`flex-grow` is used to control the proportion of available space inside a flex container that a flex item should take up. It accepts a unitless value and serves as a means to dictate how much a flex item should grow if necessary. By default, the value is 0, meaning the item will not grow.

If all items within a flex container have a `flex-grow` value of 1, the remaining space will be distributed equally among all the items. If one item has a value of 2, for example, it will take up twice as much space as the others.

## Shrink

The `flex-shrink` property determines a flex item's shrink rate in comparison to other items in the container when there's insufficient space. It accepts a unitless value, with a default of 1, meaning the higher the value, the more the item shrinks.&#x20;

## Column Gap

This property **only** works when the `display` property is set to `flex`. It sets the size of the gap between the columns in a grid container.

## Row Gap

This property **only** works when the `display` property is set to `flex`. It sets the size of the gap between the rows in a grid container.


# Spacing

Margin and padding

<figure><img src="/files/FxqwrtV5PFZsHPFw31aL" alt=""><figcaption></figcaption></figure>

## Margin

Margin is the space outside of an element, between the element and its surrounding elements.

## Padding

Padding is the space within an element, between the element's content and its border.


# Size

## Box sizing

The box-sizing property determines how the size of an element is calculated. It specifies whether the width and height of an element should include padding and borders, or just the content itself.

By default, the box-sizing property is set to `content-box`, which means that the width and height of an element only include the content and do not include any padding or borders.

Alternatively, if set to `border-box`, the width and height values of an element include padding and border. This can be useful for creating consistent element sizes, especially in complex layouts.

## Width

The `width` property specifies the width of an element. It can be set in pixels(px), percentages(%), or other length units. By default, the width of an element is automatically set by the content it contains.

Valid Example:&#x20;

* 100%&#x20;
* 60%
* 32px
* 100vh

## Height

The `height` property specifies the height of an element. It can be set in pixels(px), percentages(%), or other length units. By default, the height of an element is automatically set by the content it contains.

* 100%&#x20;
* 60%
* 32px
* 100vh

## Min Width

The `min-width` property sets a minimum width for an element. This means that if the content of the element requires a width greater than the specified minimum, the element will expand to the required size.

## Max Width

The `max-width` property sets a maximum width for an element. This means that if the content of the element requires a width greater than the specified maximum, it will be clipped and not visible.

## Min Height

The `min-height` property sets a minimum height for an element. This means that if the content of the element requires a height greater than the specified minimum, the element will expand to the required size.

## Max Height

The `max-height` property sets a maximum height for an element. This means that if the content of the element requires a height greater than the specified maximum, it will be clipped and not visible.

## Overflow X

The `overflow-x` property specifies what to do with content that overflows an element's width. The values it can take are `visible`, `hidden`, `scroll`, and `auto`. The `visible` value will display the overflow content, the `hidden` value will hide the content, the `scroll` value will display a scrollbar when necessary, and the `auto` value will display the scrollbar only when necessary.

## Overflow Y

The `overflow-y` property specifies what to do with content that overflows an element's height. The values it can take are `visible`, `hidden`, `scroll`, and `auto`. The `visible` value will display the overflow content, the `hidden` value will hide the content, the `scroll` value will display a scrollbar when necessary, and the `auto` value will display the scrollbar only when necessary.\
\
\ <br>


# Position

The position property is used to specify the type of positioning method used for an element. It determines how an element is positioned within a document, and it can affect the behavior of other elements as well.

There are five values of position: static, relative, absolute, fixed, and sticky.

1. `Static` (default value):

This sets the position of an element to its default, which means the element will flow into the page as it normally would, without any special positioning.

2. `Fixed`:

This sets the position of an element to a fixed position relative to the viewport, meaning it will remain in the same place even if the page is scrolled.

3. `Relative`:

This sets the position of an element relative to its default position, allowing you to offset it from that default position with `top`, `right`, `bottom`, and `left` properties.

4. `Absolute`:

This sets the position of an element relative to the nearest positioned ancestor element, or the viewport if there is no positioned ancestor.

5. `Sticky`:

This sets the position of an element to `fixed` within its parent container, but only after a certain threshold has been met. For example, an element with a `position: sticky` value will remain within its parent container until the user scrolls to a certain point, at which point it becomes `fixed` and stays in the same place on the screen as the user continues to scroll.


# Typography

## Font size

This property sets the size of the text. The size can be specified in various units such as pixels (px), ems (em), or percentages (%). The default font size is 16 pixels.

## Line height

This property sets the height of each line of text, and it determines the vertical space between the lines. The line height can be specified in various units such as pixels (px), ems (em), or percentages (%).

## Text color

This property sets the color of the text. The color can be specified using various color models such as RGB, HEX, HSL. Default color is black.

## Font weight

This property sets the thickness of the text. The value can be specified using keywords such as bold, normal, or a numeric value between 100 and 900.

## Font style

This property sets the style of the text. The value can be specified using keywords such as italic or normal.

## Text decoration

This property sets the decoration of the text. The value can be specified using keywords such as underline, overline, line-through, or none.

## Text align

This property sets the horizontal alignment of the text. The value can be specified using keywords such as left, right, center, justify, or inherit.


# Background

## Background type

### Background Color:

The background-color property sets the background color of an element. It can be specified using a color name (e.g. "red"), a hexadecimal value (e.g. "#ff0000"), or an RGB value (e.g. "RGB(255, 0, 0)") or RGBA (e.g. "RGBA(255,0,0,0.5)")

### Background Image(bglmg):

&#x20;The background-image property sets an image as the background of an element. The URL of the image can be specified in the value of the property.


# Border

## Radius

Border radius is a property that is used to create rounded corners on an HTML element. It can be used to add a more organic and visually appealing look to designs. You can set different values for each corner.

## Borders

Border is a CSS property used to create a visible boundary around an element. It can be used to create simple or complex designs depending on the border width, style, and color.

* Border width: Specifies the width of the border. It can be set using a length value.
* Border style: Specifies the style of the border. It can be set using a variety of values, including "solid", "dashed", "dotted". The default value is "none".
* Border color: Specifies the color of the border. It can be set to a color name, a hexadecimal value, an RGB value, or an HSL value. The default value is the current color of the element.


# Effect

## Cursor

`cursor` is a property that sets the type of cursor to be displayed when the mouse pointer is over an element. It is used to specify the mouse cursor's appearance when it is over an element. There are several pre-defined cursor types that can be used, including pointer, crosshair, help, and move, among others.&#x20;

## Color Scheme

`color-scheme` is a property that specifies the preferred color scheme for the user interface of the web page.


# Form Check

Form elements have a Form Check section to validate user inputs.

By default, it comes with a validator for required fields. By toggling Required, you can require the user to enter an input. If no input is entered, the error prompt will be shown.

![](/files/7Ov7Hmexqapq8kf9v2j2)

You can also add validators, such as checking if the input is an email.

![](/files/LfHOI3HTNPxsKQJjklvf)

Select the check type. When Check Value is toggled on, the validator will be on. Type in what text to display when there's an error into Error prompt.


# Tooltip

Tooltips display text labels when a user hovers over an element.

<figure><img src="/files/RQYNpjhpiZRfZIp2qB4w" alt=""><figcaption></figcaption></figure>

**Show tooltip:** Toggle whether tooltips are shown.&#x20;

**Content:** What will be displayed in the tooltip?

**Show arrow:** Toggle whether the tooltip will contain an arrow.

**Max width:** Set maximum width of the tooltip.

**Placement:** Choose placement of the tooltip relative to the user's cursor.

**Trigger:** Choose whether the tooltip is triggered by a user hovering over or clicking on an element.

**Show delay:** Delay time to display tooltip.

**Hide delay:** Delay time to hide tooltip.

**Follow cursor:** How would you like the tooltip to follow your cursor? It can follow along the x-axis, y-axis, both, or none.

**Interactive:** When this is toggled on, users will be able to hover over and click inside the tooltip.


# Accessors

Accessors allow you to retrieve and use data from a query result or from a data store variable. The data can be used to set element properties and styles, and can also be used in an event payload. For more information on accessors specific to event payloads, see [Event payload](/app-builder/app-construction/interactions/event-payload).

## Data structure overview

There are 3 levels of access: element level, page level, and app level. These levels define the scope of the data, or in other words, which pages or elements will have access to it.

In the below table, you'll find 4 data categories as well as their corresponding accessor.&#x20;

Categories include element, page, and app data -- which fall under the [Data Store](/app-builder/app-construction/data-store) source -- and [Query](/app-builder/app-construction/query).

<figure><img src="/files/sEgwshr9SJguBgo7DgCj" alt=""><figcaption></figcaption></figure>

## App level: app data and query results

All elements across all pages can access data stored in app data and query results.&#x20;

* To access app data, use `${#app.variable_name}` to access
* To access query results, employ the syntax `${#query_name}`. **Ensure that the query is renamed to a valid name**. Valid query names should start with a letter or underscore `_`, followed by a combination of letters, numbers, and underscores, with no spaces allowed.

For example, if you want to access a single value from a query "car\_database" in a text:

<figure><img src="/files/hqPuWmy3W7TB6TmBZkec" alt=""><figcaption></figcaption></figure>

<div align="left"><figure><img src="/files/jV48ZkcJep36yTJejBsp" alt=""><figcaption></figcaption></figure></div>

<div align="left"><figure><img src="/files/ifyssyUQESBRcn8PbfiL" alt=""><figcaption></figcaption></figure></div>

## Page level: page data

All the elements on a given page can access its page data. In the diagram below, you'll see that elements A and B on page 1 are not able to access page data for page 2.

<figure><img src="/files/l1IvLXavKoFZc4tkcq3c" alt=""><figcaption></figcaption></figure>

## Element level: element data

Element data stores variables associated with a specific element. Only the element itself can access the data.

As seen below, element B cannot access element data for element A, and vice versa.

<figure><img src="/files/oSv9u9InXfbnOACLrmRN" alt=""><figcaption></figcaption></figure>

### Element data example

Suppose we have a container that we would like to hide, and only show when a user triggers it to display by clicking on a "show more" button.

Here's how we can use element data to initially hide the container, and then unhide it when a user clicks a button.

1. Select the container. In the **Data** tab of the left panel, add a new element level data field. Name the variable `display`, set its type as string, and initialize the value to `none`.\
   ![](/files/YzVOjhkBb3gA6G907Z3r)
2. Open the **Style** tab in the right panel, and find Layout -> Display. Use the element data accessor, `${display}`, to set the display. By default, this will be `none`.\
   ![](/files/bDoTtrWJIaZdUZEWBWNP)
3. To show the container, add an interaction to change the display value. In this example, an interaction has been added to a button. In the action panel, select the container, and choose Set Data as the action. Then define the field (name of the variable) and value. This will change the display from `none` to `inline`, and show the now-inline container.<br>

   <figure><img src="/files/oRnma8STMucW867Hjh7m" alt=""><figcaption></figcaption></figure>

### Element data exceptions

In general elements will not be able to access other elements' element data. However, there is an exception to this when it comes to **inheritance**. Some elements, such as lists or tables, allow other elements to access their element data via accessors.

#### Lists

Elements inside of a list will be able to use accessors to retrieve the list's data. For more details on list accessors, see [List](/app-builder/app-construction/elements/layout-elements/list).

<figure><img src="/files/Wwk6byiouOmEGLk1SkA2" alt=""><figcaption></figcaption></figure>

#### Tables

Similarly, elements within a table will be able to access the table's column key and row data.

<figure><img src="/files/vIHSxA5gJkQkjUpvslXl" alt=""><figcaption></figcaption></figure>

## Practical example: Interactive Highlight color

Here is an example to use the techniques above to highlight number of interest.

1. Create query node

   &#x20; ![](/files/vMxxXTLXeK52L3Pzkbu2)
2. Create a list element and drag a text element inside, set text to ${$item.n}
3. Create a page variable called number in Data Store
4. Create a input element to set page variable(See details in [Data Store](/app-builder/app-construction/data-store))
   1. Set Config -> Property -> Input type to 'number'
   2. Add interactions, attention: Set Action Parameters as the figure below, enter `number` (Page variable name) in `Field` and `${event.value}` in `Value`.

      <figure><img src="/files/Lk8UTuMlxBtQZasOhCnQ" alt=""><figcaption></figcaption></figure>
5. Set text element styles parameters
   1. set width and height to 64px
   2. set background color to `${$item.n==#page.number&&'red'||'green'}`
6. Click 'Preview' to see the final result. Enter any number between 1 to 10 in the input to activate highlight number.<br>

   <figure><img src="/files/6ru38ewKeCcsTNHZrT5z" alt=""><figcaption></figcaption></figure>


# Plugin Store

A published plugin in the plugin store is a set of predefined custom API templates with a list of shared values such as credentials. The Plugin Store <img src="/files/quQwXENBf8KUs4QnFecF" alt="" data-size="line">is the place for all published plugins. To find the plugin store, enter the app that you want to use plugins, and find <img src="/files/pk6uQKrHzYYoYL2Zh1ko" alt="" data-size="line">at the left tool bar.

<figure><img src="/files/MsSqoQPK5vLBOiukpI5R" alt=""><figcaption><p>Four plugins listed in plugin store</p></figcaption></figure>

### Install Plugin

1. Navigate to the Plugin Store within your application.
2. Select and **Install** the desired plugin.

<figure><img src="/files/UvmKPLInn5lcBp2gtlJw" alt=""><figcaption></figcaption></figure>

### Add to API Services

You are able to choose between adding every supported API endpoint or only the selected ones.

1. Select the API endpoints you want to add.
2. Click the **Add to API Services** button.

### Use Plugin API in [interactions](/app-builder/app-construction/interactions)

After add the plugin to API Services, it can be found it in Interactions - Action - API Service - Your Plugin API.&#x20;

<figure><img src="/files/0nmEtykUTSdR02eC9jla" alt="" width="563"><figcaption><p>Add a "Send a email" Plugin API to a button</p></figcaption></figure>

#### Example

See a comprehensive tutorial on&#x20;

{% content-ref url="/pages/94KbJUyt1nokuzTTpgSg" %}
[Send an Email via Mailjet Plugin](/app-builder/popular-use-cases/send-an-email-via-mailjet-plugin)
{% endcontent-ref %}


# Popular Use Cases

{% content-ref url="/pages/og3PEFp5M4t2AH2iI3o5" %}
[Create a table](/app-builder/popular-use-cases/create-a-table)
{% endcontent-ref %}

{% content-ref url="/pages/8Cn9MCXvP1scAoJYHGjk" %}
[Create a list](/app-builder/popular-use-cases/create-a-list)
{% endcontent-ref %}

{% content-ref url="/pages/UBLdfRNCnK59uTY5jQ5t" %}
[Create a filter](/app-builder/popular-use-cases/create-a-filter)
{% endcontent-ref %}

{% content-ref url="/pages/qSWZ8ULLBttCR8H10RMy" %}
[Create a search bar](/app-builder/popular-use-cases/create-a-search-bar)
{% endcontent-ref %}


# Build a chart from Table Nodes

Acho app builder provides a seamless workflow to for creating charts using [Table Nodes](/app-builder/app-construction/table) with **no-code**. This enables users to efficiently transform their data into meaningful Business Intelligence or Data Science visualizations.

{% embed url="<https://www.youtube.com/embed/qe7sTXQ_LDg?si=THuko56O3YclXhS8>" %}

## Prepare your data

In this tutorial, we will use `digital_ads_performance` data from sample Postgre dataset. You can also prepare your own data and [add it to resource](/acho-studio/resources/add-a-resource) to proceed the following steps.&#x20;

<figure><img src="/files/q4ZQvP9CaoxKJvESCZop" alt=""><figcaption><p>Upload csv data to resource</p></figcaption></figure>

## Create an app

[Create an app](https://docs.acho.io/app-builder/popular-use-cases/pages/pQtQTJTksAVpD2MpwPqG#3.-create-a-blank-app-or-build-with-a-template.) if you don't have one, or go to the app that you want to create a chart.

### Drag a chart element onto page

To add a table to your page, go to **Elements  -> Chart** at left tool bar and drag it onto the page.

<figure><img src="/files/bP6A6yeX8jBSmxxj1OR7" alt=""><figcaption><p>Drag a chart</p></figcaption></figure>

### Select Data source of the chart

Select `digital_ads_performance` in **Table Node -> sample-postgre** as the Data source of your chart.

### Select Chart Properties

#### Select Chart type

Choose a chart type to load a template. For example, in the video, we use Pie chart and Line chart to visualize the `digital_ads_performance` data.

#### Select Dimension and Metric

* **Dimensions**: These represent qualitative data and serve as categories or labels for your data. They provide the contextual aspect—answering the 'what'—to help make sense of the corresponding metrics.
* **Metrics**: These are quantitative data points. They offer measurable insights to questions such as "How much?", providing a context in which the numbers (metrics) can be understood.

For example, choose 'Pie chart' as the chart type, 'channel' as the Dimension, and 'impressions' as the Metric, and you will get a chart like this:

![](/files/YJEfwT1AKUeKcIXJHP5X)

#### Aggregate data with Dimension and Metric

Furthermore, you can modify how the raw data is grouped and aggregated before generating the chart, all without needing any coding.

For enhanced visualization, charts aggregate Table node metrics, grouped by the dimension you selected.  You can choose measures of aggregation, such as sum or average for numeric metrics, and count or count distinct for non-numerical metrics. The table node data will be grouped and ordered by the dimension, and the metrics will be aggregated in the backend according to your chosen measures. Subsequently, the chart renders this aggregated data to provide an optimal visualization.

![](/files/BUbQCmLdLmedj7CvhMQv)


# Create a table

Here, we'll walk you through an example for how to create and configure a table element. For information about the table element and more general instructions on how to add/hide columns, visit [Table](/app-builder/app-construction/elements/table-and-chart/table).&#x20;

The table that we will be recreating in this tutorial is the table for our data validation app. We'll show you how to prepare your data and configure the table, including adding a column of checkboxes, displaying images, constructing columns with multiple pieces of information, adding currency symbols such as "$" or "%", and creating columns that only display values.

<figure><img src="/files/46EGH3VlUZBz5rBRPlU8" alt=""><figcaption></figcaption></figure>

## Prepare your data

In this tutorial, we will use a sample Shopify products dataset to build the table, you can download the data [here](https://storage.googleapis.com/acho-prod-assets/acho-website-assets/live_demo/sample_products.csv) and [add it to resource](/acho-studio/resources/add-a-resource).&#x20;

<figure><img src="/files/q4ZQvP9CaoxKJvESCZop" alt=""><figcaption></figcaption></figure>

## Create an app

[Create an app](https://docs.acho.io/app-builder/popular-use-cases/pages/pQtQTJTksAVpD2MpwPqG#3.-create-a-blank-app-or-build-with-a-template.) if you don't have one, or go to the app that you want to add a table

### Drag table element onto page

To add a table to your page, go to **Create -> Elements  -> Table** and drag it onto the page.

<figure><img src="/files/RJKumNWGljNImykouuoq" alt=""><figcaption></figcaption></figure>

### Configure your table

Select the table and navigate to **Property** located at the right configuration panel. Select the [**Table Node**](/app-builder/app-construction/table) of your data from the **Data source** dropdown menu.&#x20;

<figure><img src="/files/80byb9PKXB4piwfV0nL0" alt="" width="346"><figcaption></figcaption></figure>

If you'd like, there are additional styling options, including header and row sizes, you can change below. See [Table](/app-builder/app-construction/elements/table-and-chart/table) for more on these options.

The next step is to build your columns. By default, the table will display all columns with no styling, similar to the data node preview we saw from step 1.

<figure><img src="/files/8f8B9fReGgS8veJRk4Bw" alt=""><figcaption></figcaption></figure>

#### Configure columns

To configure each displayed column, we can build them individually by adding columns under Config -> Property. To add a column, click on the <img src="/files/vz6ePyV3xj7LswqSbO8N" alt="" data-size="line"> under Columns. Then, we'll build our table column by column.

The key of a column setting will be the name of a column in your data node that will be replaced by your configuration. The title will be the displayed header on your table.

1. **Hide and arrange columns:**\
   Drag the columns to rearrange them and click <img src="/files/TyDzuI9lVDqQ9K213e5r" alt="" data-size="line">to hide those columns that you don't want to present.<br>

   <figure><img src="/files/G6TpMoHHthzO2uFhyfeJ" alt=""><figcaption></figcaption></figure>
2. **Rename Columns:**\
   Click on columns to rename the title of the column\
   ![](/files/MUannaeWEA0eLIH4sPBw)
3. **Edit column elements**\
   If you want to display more than a text of the table value, click the <img src="/files/TyDzuI9lVDqQ9K213e5r" alt="" data-size="line">icon on the table level to enter <img src="/files/1KvHzdsPQzRXylwMYC7b" alt="" data-size="line">editing mode from preview. Then you will need to use [accessor](/app-builder/app-construction/accessors)[s](/app-builder/app-construction/accessors) to access the value of the cell. For example, drag an image element in the product\_image cell, and set its url to `${$value}` , the product\_image column will display the images of the product.<br>

   <figure><img src="/files/8i51a8u3kTeRMeNlntTk" alt=""><figcaption><p>Drag an image element in the product_image cell</p></figcaption></figure>
4. **Use multiple columns value in one cell**\
   Additionally, you can access values from other columns, such as 'product\_name', by using <mark style="color:red;">`${$row.product_name}`</mark>.Similarly, <mark style="color:green;">`${}`</mark> tells the system that you are using an [accessor](/app-builder/app-construction/accessors) to access data. <mark style="color:red;">`$row.product_name`</mark> means to extract the value of the <mark style="color:red;">`product_name`</mark> key in each row.\
   ![](/files/cuN9ZAHHQjzlx2OtwWFS)![](/files/XATLAZgiWM3s8EIdL4xE)\
   Use containers to arrange the elements.
5. **Price, Stock, Promotion:** These columns have a simple configuration since they display their value without including data from other columns.\
   ![](/files/sbsC0eElvqzbDE06xDoN)\
   Their values are accessed with <mark style="color:red;">`${$value}`</mark>. To add certain format, we can add a separate "$" before the<mark style="color:red;">`${$value}`</mark> for price, and a "%" after the <mark style="color:red;">`${$value}`</mark> for promotion value. \
   \
   ![](/files/hrdg4KkFbzZdjPc95xFj)![](/files/RB7nV9QPnDyqx6wua2NQ)<br>

### Set your table style

Set the size of your table under **Config -> CSS -> Size**.

Set the header color under **Config -> Element Styles -> Header Background Color**

![](/files/hMSaVY94aOIJ7xeGfOPh)![](/files/TpoJZHeJmMj9lepEb1GQ)

This is what our final table will look like:

<figure><img src="/files/BzSy9OCLI3QrcDQZjqOI" alt=""><figcaption></figcaption></figure>


# Create a list

The [**List**](/app-builder/app-construction/elements/layout-elements/list) element is another valuable tool for presenting elements that follow a common pattern. It is to turn data into a more flexible format instead of a tabular format. Compared to [**Table**](/app-builder/app-construction/elements/table-and-chart/table), **Lists** offer the advantage of creating a more dynamic user interface through CSS techniques such as Flex and Grid. The list element digests an JSON array and convert the array to a list of elements with the same pattern.

![](/files/wVl6PCHrpVYgoHuveIMK)

## Prepare your data

In this tutorial, we will use a sample Shopify products dataset to build the list, you can download the data [here](https://storage.googleapis.com/acho-prod-assets/acho-website-assets/live_demo/sample_products.csv) and [add it to resource](/acho-studio/resources/add-a-resource).&#x20;

<figure><img src="/files/q4ZQvP9CaoxKJvESCZop" alt=""><figcaption></figcaption></figure>

## Create an app

[Create an app](https://docs.acho.io/app-builder/popular-use-cases/pages/pQtQTJTksAVpD2MpwPqG#3.-create-a-blank-app-or-build-with-a-template.) if you don't have one, or go to the app that you want to add a table

### Drag list element onto page

To add a text to your page, find  **Elements -> List** and drag it onto the page.

### Add elements into list

Make sure the list is on editing mode, then drag a **Text** element into the list and type <mark style="color:red;">`${$item.product_name}`</mark> .  <mark style="color:green;">`${}`</mark> tells the system that you are using an [accessor](/app-builder/app-construction/accessors) to access data. <mark style="color:red;">`$item.product_name`</mark> means to extract the value of the <mark style="color:red;">`product_name`</mark> key in each JSON object.

<figure><img src="/files/m6BobRKaUnn8CMwYcZuV" alt=""><figcaption></figcaption></figure>

Similarly, add another text and an image into the list, use <mark style="color:red;">`${$item.image_url}`</mark> as the image url and <mark style="color:red;">`${$item.stock}`</mark> for the text. Use container to control the layout

Click the **Preview** button to see the result. As you can see, all the values in your data are shown on the page. &#x20;

![](/files/IlLekH7UySDrUIwyoLvk)

### Use CSS to control list layout

Select the list element and try setting the layout to either "Display: `Flex`" with a direction of "`Row`," or "Display: `Grid`" with columns set to "`1fr 1fr 1fr`"

<figure><img src="/files/a0C6DJB7zGxjNP1Mtqn8" alt="" width="375"><figcaption><p>Flex + Row</p></figcaption></figure>

<figure><img src="/files/yYCDC1T3MXZtbDnHkFA9" alt="" width="375"><figcaption><p>Gird + 1fr 1fr 1fr</p></figcaption></figure>


# Create a filter

Combining [Query node](/app-builder/app-construction/query) and [Interactions](/app-builder/app-construction/interactions), you can allow users to filter data based on their input. This tutorial will show you how to use Form to collect user's input, use interaction to set SQL parameters in query nodes and filter a table.

Examples in this tutorial will reference table `company_daily_stock_price` containing stock information, you'll find the table in the sample Postgres database.

<figure><img src="/files/de9guD9YAoZ1g4JvKTBo" alt=""><figcaption><p>company_daily_stock_price</p></figcaption></figure>

## Setting up your query node

In order to use user inputs to change SQL parameters to filter your data, you'll need to add parameters to your node. The syntax to add parameters varies slightly based on the type of data node you are using. See [Query](/app-builder/app-construction/query) for syntax details and more information on parameters.

Consider the data type output by the element triggering the filter. For example, a [Switch](/app-builder/app-construction/elements/form-elements/switch) element produces a boolean value, or a [Multiselect](/app-builder/app-construction/elements/form-elements/multiselect) produces an array. When initializing parameters, you'll want the initialized value to be of the same data type.

When building your query, you'll also want to make sure that the data type of the parameter matches the column that it's filtering. Your statement should handle any necessary type casting or additional processing.

The following examples are all queries made in PostgreSQL query nodes. To create such a query node, locate the `company_daily_stock_price` in table node list and create a query node from it.

<figure><img src="/files/QmjwfFj2g2nADistYfmC" alt=""><figcaption><p>Create the query node from <code>company_daily_stock_price</code> table node</p></figcaption></figure>

### Example: Numerical and string inputs

This example shows how to deal with numerical and string columns.

It will pull all records where `total_volume` is greater than or equal to the user's input for `min_volume`, and where `exchange_short` matches what the user selects. The query was built and parameters were initialized so all data is shown before the user selects any filters.&#x20;

<figure><img src="/files/0Q4qWqErWRwClfZruW0K" alt=""><figcaption></figcaption></figure>

Query:

```sql
SELECT ticker, company_name, exchange_short, volume, close, change 
FROM company_daily_stock_price
WHERE volume >= {{min_volume}}
AND exchange_short LIKE CONCAT('%','{{exchange}}','%');
```

Parameter initialization (See how to set parameter in [/pages/uHfRIhYYIjWrmxqZdTNt#1.-add-new-parameter](https://docs.acho.io/app-builder/popular-use-cases/pages/uHfRIhYYIjWrmxqZdTNt#1.-add-new-parameter "mention")):

```sql
{
  "min_volume": 0,
  "exchange": ""
}
```

The parameter `min_volume` is initialized to `0`, a numerical value that can be compared against the column `total_volume`. `exchange` is initialized as an empty string, and in the query, turned into a [Regex](https://dataschool.com/how-to-teach-people-sql/how-regex-works-in-sql/) expression using the `CONCAT()` function. This allows all records to be pulled when the string is empty, and will match specific values when the parameter value is changed.

### Example: Array input

Some form elements output arrays. For example, let's say we plan on having a [Multiselect](/app-builder/app-construction/elements/form-elements/multiselect) input element where I allow users to choose which ticker values they'd like to see data for, and display all rows where the ticker matches.

<figure><img src="/files/i6uZF2I2v7cfYsmJsgOI" alt=""><figcaption></figcaption></figure>

Query:

```sql
{% set comma = joiner() %}

SELECT ticker, company_name, exchange_short,  volume, close, change 
FROM company_daily_stock_price
WHERE 

{% if ticker_list | length > 0%} 
ticker IN ({% for ticker_item in ticker_list %}{{ comma() }} '{{ticker_item}}' {% endfor %}) 
{% else %} TRUE
{% endif %};
```

Parameter initialization:

```sql
{
  "ticker_list": [],
  "ticker_item": ""
}
```

This example shows how you can pull all records for the tickers that the user has selected. In this statement, if `ticker_list` is not empty, we use a for loop to reconstruct the array in the right format and check if `ticker` appears in it. If the array is empty, all records will be displayed.

## Create your elements for filtering

A common way to create a filter is to insert [Form Elements](/app-builder/app-construction/elements/form-elements) into a [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form). The form can then collect the inputs and use them to change your SQL parameters.

Following from the data node examples above, we've created a form, which contains an [Input](/app-builder/app-construction/elements/form-elements/input) element to collect the minimum total volume, a [Radio Button](/app-builder/app-construction/elements/form-elements/radio-button) to select an exchange, and a [Multiselect](/app-builder/app-construction/elements/form-elements/multiselect) to select tickers.

![](/files/EMijA6hPS1jM5lInuMrF)

Each form element has a form item name, which is the name that the form will use to access the user input. They're also configured based on the specifications in our query.

* **Minimum volume:** The `total_volume` column is numerical, so we'll want to process the input as a number.\
  ![](/files/Kj4fiV8svK9yLZzU3Sni)
* **Exchange:** Recall that in our query, we display all records when the `exchange` parameter is an empty string. So when a user selects the "All" option, the value we're changing the parameter to is empty.\
  ![](/files/F1F08fcJjvxHUvWJPA0U)
* **Tickers:** Add ticker values for the user to choose from. Either enter the value:label pairs into  the input boxes, or click on `</>` under Options to use an accessor to an array of objects with `"label"` and `"value"` keys.\
  ![](/files/Z39w1bX2HH9Zpo3mEX3f)

## Create the interaction to change SQL parameters

Once the form elements and data node have been set up, the last step is to create the interactions that will change the SQL parameters.

### What the form will do when it's submitted

Add interactions to change SQL parameters on the form element when it is submitted.&#x20;

Add a Submit event block to the form, and create an action. Select API Service -> Set SQL Parameter. Make sure you're setting parameters under the right data node.

Access the user inputs from the event payload using `${event.form.min_volume}` and `${event.form.exchange}`.

<figure><img src="/files/nLiGtjc5nBPzPw5F2qBv" alt=""><figcaption></figcaption></figure>

Similarly, the interaction to filter tickers can be accessed with `${event.form.ticker_list}`.

<figure><img src="/files/LWNkmAbxhozyT3q6oHLr" alt=""><figcaption></figcaption></figure>

### Submitting the form

We've set up the interactions to change SQL parameters upon submission of the form. However, we still need to create a way to submit the form.

On an element, such as a button, set up an interaction to submit the form.

<figure><img src="/files/S1bfFkAy9MCu13wavJ9R" alt=""><figcaption></figcaption></figure>


# Create a search bar

A search bar can help users easily filter data and find the content they're looking for.

This tutorial will walk through how to use a [Search Bar](/app-builder/app-construction/elements/form-elements/search-bar) to find data. For other ways to filter, see [Create a filter](/app-builder/popular-use-cases/create-a-filter).

The search bar works by accepting user input, then changing a SQL parameter in a **Query** to filter the data accordingly. If a table is using this specific query node as its data source, the table contents will reflect the output of the search.

<figure><img src="/files/OriV7L6oJEWR3OT2y8OR" alt=""><figcaption></figcaption></figure>

In this tutorial, we'll reference the following table:

<figure><img src="/files/de9guD9YAoZ1g4JvKTBo" alt=""><figcaption><p>company_daily_stock_price</p></figcaption></figure>

## Setting up the Query

The first step to creating a search bar is to set up a **Query** with a SQL parameter. Add a **Query** from your **Table**, then double click to open it. Syntax for creating query and parameters can differ depending on the type of the database. See [Query](/app-builder/app-construction/query) for syntax and parameter details.

The following searching examples are all queries made in PostgreSQL query nodes. To create such a **Query**, locate the `company_daily_stock_price` in table node list and create a **Query** from it.

<figure><img src="/files/QmjwfFj2g2nADistYfmC" alt=""><figcaption><p>Create the query node from <code>company_daily_stock_price</code> table node</p></figcaption></figure>

### Basic search

A basic search will find all records that match the search value exactly. For example, let's say we want to search based on the column `ticker`.

First, we need to insert a parameter to represent the search value. Click the plus button ![](/files/TGiWq6LC3SqDUUJUBHY6)at the parameter panel to add a parameter. In the example below, I add a string parameter named "name", and set the default value to "" (empty string).

#### Basic search: Case-sensitive

The following query will pull records that match the company name exactly, including capital and lowercase letters. If there is no search value, the entire table will be displayed.

<figure><img src="/files/Hm8N6Qib4ZfdL8N1vdcc" alt=""><figcaption></figcaption></figure>

Query:

```sql
SELECT * 
FROM company_daily_stock_price
WHERE ticker = '{{name}}'  or '{{name}}' = ''
```

#### Basic search: Case-insensitive

The query can also be case-insensitive, pulling all matching records regardless of capital or lowercase letters. This is accomplished by adding LOWER() function at both.

<figure><img src="/files/IO4u7NIsnOzIyHlhyIx6" alt=""><figcaption></figcaption></figure>

Query:

```sql
SELECT * 
FROM company_daily_stock_price
WHERE LOWER(ticker) = LOWER('{{name}}')  or '{{name}}' = ''
```

### Full-text search

A full-text search will match all records that contain the search value. This will require us to turn the parameter value into a regular expression, or [Regex](https://dataschool.com/how-to-teach-people-sql/how-regex-works-in-sql/), using the `CONCAT()` function.&#x20;

The following query will concat a `%` symbol to either end of the parameter value. This tells the query to match all records that contain the search value, regardless of additional characters preceding or following it.&#x20;

It is also case-insensitive. For example, the searches `App`, `ple`, and `apple` will all match with `Apple Inc.`. When there is no search value, all records will be matched.

You may also construct other regex patterns to further customize your search.

<figure><img src="/files/oEdZAySCtcbduwjK7thU" alt=""><figcaption></figcaption></figure>

Query:

```sql
SELECT * 
FROM company_daily_stock_price
WHERE ticker LIKE CONCAT('%', '{{name}}', '%');
```

### Full-text Search(Case-insensitive)

In addition to a regular full-text search, you can perform a case-insensitive search by applying the `LOWER()` function to both expressions that surround the `LIKE` operator. This will ensure that the search is not sensitive to uppercase or lowercase characters, allowing for a more flexible search.

<figure><img src="/files/umIWG78Z1L0nbif6ssj6" alt=""><figcaption></figcaption></figure>

Query:

```sql
SELECT * 
FROM company_daily_stock_price
WHERE (LOWER(ticker) LIKE CONCAT('%',LOWER('{{name}}'),'%'));
```

By using the `LOWER()` function, the `company_name` and search `name` values are converted to lowercase before comparison, enabling case-insensitive matching. This means that regardless of whether the characters are uppercase or lowercase, the search will match the corresponding records.

### Global search

In addition to individual column searches, you can perform global searches that search across multiple columns. This can be done by adding `OR` operators in the `WHERE` clause. The following example performs full-text global searches across two columns: `company_name` and `ticker`.&#x20;

<figure><img src="/files/lxY7kW7i03BaHtsFYuys" alt=""><figcaption></figcaption></figure>

Query:

```sql
SELECT * 
FROM company_daily_stock_price
WHERE company_name LIKE CONCAT('%', '{{name}}', '%')
    OR ticker LIKE CONCAT('%', '{{name}}', '%');
```

## Search by filtering the data

Once the node is ready, create a search bar on your page by using the [Search Bar](/app-builder/app-construction/elements/form-elements/search-bar) element group.&#x20;

<figure><img src="/files/kcHL5epXxh6rFULYq1CT" alt=""><figcaption></figcaption></figure>

The search bar has a supported Search event that is triggered when a user clicks on the Search button or when the user presses Enter.

Use the search event to create an interaction on the search bar to set the SQL parameter in your **Query**. In the action parameters, use `${event.value}` to access the user's search value.

<figure><img src="/files/UeDKFbteZPfsltSRjmlr" alt=""><figcaption></figcaption></figure>


# Use Custom Form Container to collect user inputs

A [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form) can be used to collect user inputs from other [Form Elements](/app-builder/app-construction/elements/form-elements). These inputs can then be used to perform a variety of actions, including to filter your data, run models, and write back to databases.

## How does the Form Container work?

A [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form) can contain multiple form elements, which the user will be able to interact with. This can include checkboxes, radio buttons, etc. Whenever a user interact with these elements, such as selecting an option or inputting a value, their input is sent to the nearest form.

When you create interactions on the form, you'll be able to access the values outputted by the user with the accessor `${event.form.item_name}`.

### What if there are nested forms?

If there are nested forms, inputs are sent to the nearest form.

In the example below, you'll see two nested forms. Form 1 will be able to access values for Input 1 and Input 2, while Form 2 only has access to Input 3. Since inputs are only sent to the nearest form, Form 1 will not be able to access Input 3.

![](/files/yqsmgry3KEWkeCoeSBy1)

## How to create your form

1. Drag a [Custom Form](/app-builder/app-construction/elements/form-elements/custom-form) onto your page.
2. Build your layout, including [Form Elements](/app-builder/app-construction/elements/form-elements), inside of the form. This example contains an [Input](/app-builder/app-construction/elements/form-elements/input), [Radio Button](/app-builder/app-construction/elements/form-elements/radio-button), and [Multiselect](/app-builder/app-construction/elements/form-elements/multiselect).\
   ![](/files/rfTACwopxZaYnKGxrILr)
3. Set the **form item name** for each form element. This is the name that the form will use to access the user input. For example, this element has a form item name `min_volume`. In an interaction on the form, it will be accessed through `${event.form.min_volume}`.\
   ![](/files/PRNz0crcF8TJe5mYM0K1)
4. Configure each element. In the example above, we want to the `min_volume` input to be a number, so we set the input type to number. Other elements may require you to set a list of options for the user to choose from.\
   &#x20;![](/files/Au3lXr3hNwadOsxEcd1t)\
   For example, this radio button gives users 3 options to choose from. In each pair of inputs, the top value is the value returned by the element and sent to the form. The bottom is the display name.\
   \
   Other elements, such as the multiselect, will return an array of selected values. See each element's page for more details on how it is configured and how values are outputted.&#x20;

## Interactions to submit the form

Once the form has been set up, the last step is to create 2 interactions to be able to use the user-inputs.&#x20;

1. On the form: Trigger actions to perform when the form is submitted.
2. On the submit button: Trigger the form to submit.

In this example, when the submit button is clicked, the form will be submitted and carry out the action.

![](/files/yagJDDWVNTWGDBT6h6G7)

### What the form will do when it's submitted

1. Select the form and add a supported Submit event.
2. Create an action that will use the inputs the form has collected. For example, you can use the inputs to change SQL parameters.
3. Access the user inputs from the the form's event payload using `${event.form.min_volume}`.

<figure><img src="/files/nLiGtjc5nBPzPw5F2qBv" alt=""><figcaption></figcaption></figure>

### Submitting the form

We've set up an interaction that tells the form what to do when it is submitted. However, the form will still need to be prompted to submit through an interaction on another element.

1. On another element, such as a button, set up an interaction to submit the form by selecting Element -> Form -> Submit form as the action.

<figure><img src="/files/S1bfFkAy9MCu13wavJ9R" alt=""><figcaption></figcaption></figure>


# Drill down on a table

This walkthrough tutorial will help you drill down on a table and present the results in a chart. The chart will update based on which row is clicked on the table.&#x20;

<figure><img src="/files/NKb08oc1KD7vFiw8dnrN" alt=""><figcaption></figcaption></figure>

## Set up query nodes for chart

1. Create query node(s) to use for a table and chart. These are likely to be different nodes, which will allow you filter data for a chart without changing the table.
2. On the data node for the chart, write a query with a SQL parameter you'd like to filter by. See [Query](/app-builder/app-construction/query) for more information on parameter syntax and examples. This example in a transformation node will filter based on a ticker value.<br>

   <figure><img src="/files/Yx5gM8Ka0Bl8BAtQB17v" alt=""><figcaption></figcaption></figure>

Query:

```sql
SELECT date, ticker, name, close as stock_price
FROM company_daily_stock_price
WHERE ticker = '{{ticker}}'
ORDER BY date
```

Parameter Initialization(Add a parameter named <mark style="color:red;">`ticker`</mark> with default value of <mark style="color:red;">`ORCL`</mark>):

```sql
{
  "ticker": "ORCL"
}
```

## Create your table

Create the table that the drill down will be connected to. See [Create a table](/app-builder/popular-use-cases/create-a-table). For the table, create another query node for table data. Use this query node as the **Data source** of the table.

Query:<br>

```sql
WITH RankedObservations AS (
    SELECT 
        *,
        ROW_NUMBER() OVER (PARTITION BY ticker ORDER BY date DESC) AS row_number
    FROM company_daily_stock_price
)

SELECT ticker, name, close as stock_price, volume, website, industry, subindustry
FROM RankedObservations
WHERE row_number = 1
```

## Create your chart

On the same page, drag a [Chart](/app-builder/app-construction/elements/table-and-chart/chart) element. As the chart's data source, select the query node with the SQL parameters. Then configure the chart as desired. For example, set `date` for x dimension and `stock_price` for y metric.

<figure><img src="/files/dE9WDQoW6Otw7wx1uXaS" alt=""><figcaption></figcaption></figure>

## Create the interaction

To perform a drill down, a click event on the table is used to trigger the change of query node's SQL parameter so only the data for the selected ticker is shown on the chart. For example, if we're filtering by ticker, we'll pass in `${event.rowData.ticker}` as the action parameter.

The chart will now show data for only that ticker after click on a certain row.<br>

<figure><img src="/files/nFAQaFelIFgIkPja5jHQ" alt=""><figcaption></figcaption></figure>

You can also create additional tables, or other elements, that will present your drilled-down data. For example, add a text to display the company's name. Add one more **Action - Element - Set text** after **Row Click**, then set the text to `${event.rowData.name}`

[Preview](/app-builder/preview) or [publish](/app-builder/publish) your app to see the result.

<figure><img src="/files/NKb08oc1KD7vFiw8dnrN" alt=""><figcaption></figcaption></figure>


# Download file from query node

Sometime, you want to empower your users to filter the table and download the filtered table. Acho App Builder provide an API Service to achieve this task.

Acho support download file from query nodes by action  **API Service** → **Download File**. You can add a button on your app to trigger the action and allow users to download data as a file. Follow these steps to set it up:

1. Select an element, such as a [**Button**](/app-builder/app-construction/elements/web-elements/button) or a [**Clickable**](/app-builder/app-construction/elements/web-elements/clickable), to add an interaction that will trigger the download.<br>

   <div align="left"><figure><img src="/files/8XekgenNGEjHqFQmy5H6" alt=""><figcaption></figcaption></figure></div>
2. In the Interactions panel, add a supported event(**Click Button** in this example).
3. Then, add an action, select **API Service** → **Download File**.
4. Select which data asset to download data from in the dropdown menu.("Sample\_data" is used in this example).
5. Select the file format of the download, there are two options:&#x20;
   1. CSV: Comma-Separated Values is a popular file format for storing tabular data. It uses plain text with values separated by commas.&#x20;
   2. JSON: JavaScript Object Notation is a lightweight data interchange format. It provides a structured representation of data using key-value pairs, arrays, and nested objects.&#x20;

{% hint style="info" %}
**Is Public File** determine whether or not the action will generate a public link for the file, remember to turn it on if you want to use the link to share with teammates.
{% endhint %}

In this example, when the button is clicked, it will downloads data from the node Sample\_Data as a CSV file.

<figure><img src="/files/2Khm3W4ObI8PSlhODKoO" alt=""><figcaption></figcaption></figure>


# Set loading animations

Acho provides support for setting up loading animations through actions in interactions. With the power of action flow, you can control when and how these loading animations are triggered. Loading animations add visual feedback to elements during updates or data retrieval, enhancing the user experience of your app.

You’ll be able to set up loading animations on elements when they are being updated. For example, if you filter your table, the loading animation will appear as the table is being updated.

<figure><img src="/files/6FTVLaqw6Cw2XUHjQ8Bn" alt=""><figcaption><p>Loading animation after Search begins</p></figcaption></figure>

You’ll need two interactions to set this up. One to start the animation when an event occurs, and one to stop the animation.

## Start animation

1. To start the animation, add an interaction on the element that will trigger it. This example will start a loading animation on a table when the button is clicked.
2. Choose Element as the action, and select the element that you’d like to add the animation to.
3. Then choose Set Loading as the method and set the parameter loading to `true`.

<figure><img src="/files/ZQ9fSoA2HUd8UJntplhr" alt=""><figcaption></figcaption></figure>

## Stop animation

1. To stop the animation, add an event to set loading to `false`. Select an event to trigger the animation to stop. In this example, the Event is a data update on the data node named revenue\_sample. Once the node is finished updating, the loading will stop.
2. Similarly, select Element → your page -> your element, and Set Loading. But this time, enter `false` as the loading value.

<figure><img src="/files/Ov93Og7bbukQ1JujPhjz" alt=""><figcaption></figcaption></figure>

## Set loading parameters:

When using the set loading action in our app builder software, you have the following parameters available to customize the loading behavior:

1. **Loading**: This parameter accepts only a boolean value (`true` or `false`) and determines whether the loading animation is activated or deactivated.
2. **Text**: You can specify the text to be displayed alongside the loading indicator. This parameter allows you to provide relevant information or messages to users while the loading process is ongoing.
3. **Mask Color**: This parameter defines the color of the background mask that appears behind the loading indicator. You can choose a suitable color that matches the design of your app.
4. **Text Color**: This parameter sets the color of the text displayed alongside the loading indicator.
5. **Icon Color**: This parameter sets the color of the loading icon. Select a color that aligns with your app's design guidelines and provides good visibility.
6. **Size:** This parameter determines the size of the loading indicator.

By adjusting these parameters, you can tailor the loading action to match your app's design language and provide users with better interaction experience.


# Modify a database

Writing back to a database allows users of an app to directly interact with the data. For example, if an app is collecting user-inputted data, or editing existing data, these changes will immediately be reflected in your database.

Database direct nodes connect directly to your database, so you'll be able to write SQL statements in your nodes to modify the database. This can include:

[#creating-new-tables](#creating-new-tables "mention")

[#inserting-new-records](#inserting-new-records "mention")

[#updating-existing-records](#updating-existing-records "mention")

[#deleting-records](#deleting-records "mention")

The following examples are created in PostgreSQL data nodes.

## Creating new tables

You can create new tables in your database using a `CREATE TABLE` statement.&#x20;

Specify the name of the new table after the `CREATE TABLE` keywords.

Within the parentheses, specify a comma-separated list of table columns. Each column contains:

* Column name
* Data type that the column stores
* Length of the data
* Column constraint

Column constraints specify rules that the column must follow. For example, `NOT NULL` specifies that values in the column cannot be NULL. Other column constraints include `UNIQUE`, `PRIMARY KEY`, `CHECK`, and `FOREIGN KEY CONSTRAINTS.`

When you click <img src="/files/ZFlrnA3PbhOZCKlPKpo6" alt="" data-size="line">, the node will run and a new table will be created in your database. The node only needs to be run once. Since this is a create table query, there will be nothing in the output preview table.

<figure><img src="/files/XSMP1sGIbC9BBpaq9uCl" alt=""><figcaption></figcaption></figure>

Query:

<pre class="language-sql"><code class="lang-sql">CREATE TABLE new_table (
	customer_id SERIAL PRIMARY KEY,
	first_name VARCHAR(255) NOT NULL,
<strong>	last_name VARCHAR(255)  NOT NULL,
</strong><strong> 	email VARCHAR(255)  NOT NULL,
</strong> 	uploaded_time TIMESTAMP
);
</code></pre>

This example creates a new table called `new_table` with 5 columns: `customer_id`, `first_name`, `last_name`, `email`, and `uploaded` time.&#x20;

* `customer_id`: This column is a SERIAL datatype. It will automatically be assigned a sequential integer when a new record is added. This column is designed to work as the primary key of the table.
* `first_name`, `last_name`, `email`: These columns are strings with a length of 255 characters. They also cannot contain NULL values.
* `uploaded_time`: This column stores a timestamp showing when a new record is added.

## Inserting new records

### Data node setup

New records can be inserted into an existing table with an `INSERT` statement.

Specify the name of the table you want to insert records into after the `INSERT INTO` keywords. Then list the columns you'd like to add values to.

After the `VALUES` keyword, list the values to add. Ensure that the columns and the column values are in the same order.

To insert new records based on user input, those values should be parameterized. See [Query](/app-builder/app-construction/query) for detail on adding parameters.

<figure><img src="/files/u7122RKUJgoWGVuZpP5e" alt=""><figcaption></figcaption></figure>

Query:

```sql
INSERT INTO new_table (first_name, last_name, email, uploaded_time)
VALUES ('{{first_name}}', '{{last_name}}', '{{email}}', current_timestamp);
```

This example will insert new records based on user inputs for the columns `first_name`, `last_name`, and `email`. It will also insert the current time into the `uploaded_time` column to indicate when the record was created. Since this is a Insert query, nothing will come out in the output preview table.

### User input setup

User inputs are passed in through a Form element. See [Use Custom Form Container to collect user inputs](/app-builder/popular-use-cases/use-custom-form-container-to-collect-user-inputs) for more on how to build a form to collect data and how to set up the necessary interactions.

Once the form and form elements have been created in your interface, first set up an interaction on the form to set SQL parameters in your node.

<figure><img src="/files/yEXjZ9P2TGdDSvpg7238" alt=""><figcaption></figcaption></figure>

Remember to create another interaction to submit the form.

<figure><img src="/files/UyCYyLhtztRgVd9TIJiG" alt=""><figcaption></figcaption></figure>

When the button is clicked, the form will be submitted and run the statement in your node to insert a record with the values the user has inputted.

## Updating existing records

### Data node setup

An `UPDATE` statement changes the values of columns in all rows that satisfy a condition.&#x20;

Then, in a data node, set up a statement to change the email for the `customer_id` of the row being edited.

Paramaterize the email and customer\_id values so users can input an email for any customer.

<figure><img src="/files/cuhlJ2tBGKFnZt7ub2Vg" alt=""><figcaption></figcaption></figure>

Query:

```sql
UPDATE new_table
SET email = '{{email}}'
WHERE customer_id = {{customer_id}};
```

This example changes the email address for the given `customer_id`.

After the `UPDATE` keyword, choose the table you'd like to edit.

Only the columns to be modified need be mentioned in the `SET` clause; columns not explicitly modified retain their previous values. To modify multiple columns, separate them with a comma.

In the `WHERE` clause, identify which rows will be modified with the new value. In this case, `customer_id` is a primary key, so only one row will be modified at a time. However, you can change the condition to match multiple rows to bulk edit data.

### User input setup

Let's say an app has a table to displaying data from `new_table`. Each row has a button that will open up a modal containing a form to change the customer's email.&#x20;

<figure><img src="/files/pFLvyYZZSWUaSlx1RIB5" alt=""><figcaption></figcaption></figure>

See [Create a table](/app-builder/popular-use-cases/create-a-table) for table setup with a column of buttons.

See [Modal](/app-builder/app-construction/elements/web-elements/modal) for how to create and trigger the modal popup. Make sure the modal is dragged **into** the table element, so the modal is able to access table values.

![](/files/pqeEWE1czslXNagWoDKp)

See [Use Custom Form Container to collect user inputs](/app-builder/popular-use-cases/use-custom-form-container-to-collect-user-inputs) to learn how to create a form inside the modal to collect a new email address.

![](/files/nR3FJZIgFyZmckzj7pvu)

* Customer ID: In a text element, use `${$row.customer_id}` to access the customer id for the clicked row. Since the modal is created inside of the table, it will be able to access table values.
* Email: Use an [Input](/app-builder/app-construction/elements/form-elements/input) element and name the form item `email`. This will pass in the user input to the form.

Once the form and data node are ready, set up the interactions to submit the form and update the record based on the parameter values for `email` and `customer_id`.

For the interaction on the form to set SQL parameters for the data node, pass in `${$row.customer_id}` and `${event.form.customer_id}` as the action parameters. This will run the node with the parameter values and update the record.

<figure><img src="/files/h6MXCtJVVMsxux4rZVgM" alt=""><figcaption></figcaption></figure>

Remember to add an action on the submit button to submit the form.

<figure><img src="/files/nV4BzLpdbv4G20Bz1E3n" alt=""><figcaption></figcaption></figure>

## Deleting records

### Data node setup

Use a `DELETE` statement to delete rows that satisfy the `WHERE` condition.

Similarly, the value can be parameterized.

<figure><img src="/files/FGumq0MiASGWipUMTS1n" alt=""><figcaption></figcaption></figure>

Query:

```sql
DELETE FROM new_table
WHERE customer_id = {{customer_id}};
```

In this example, we delete a row from `new_table` for a given `customer_id`.

### User input setup

Let's say an app contains a table displaying data from `new_table` and each row in the table has a delete button for that row.

<figure><img src="/files/A5JxJzFjNFlMYWeratNO" alt=""><figcaption></figcaption></figure>

See [Create a table](/app-builder/popular-use-cases/create-a-table) for table setup with a column of buttons.

When a user clicks on the delete button, the record will be deleted from the database.

On the button, add an interaction to set the SQL parameter of the data node to the `customer_id` of that row. Use `${$row.customer_id}` to access the value.&#x20;

When the button is clicked, the parameter value will be sent to the node and the node will run the `DELETE` statement to remove that record.

<figure><img src="/files/viRgiCD7m3yTuwVlHupj" alt=""><figcaption></figcaption></figure>




---

[Next Page](/llms-full.txt/1)

