Components

Components are like building blocks. They allow you to build complex UIs and display business data using attribute models. The maximum number of components per screen is 50. Please refer to best practices for components.

The following components are supported:

  1. Text (Heading, Subheading, Caption, Body)

  2. TextEntry

  3. CheckboxGroup

  4. RadioButtonsGroup

  5. Footer

  6. OptIn

  7. Dropdown

  8. EmbeddedLink

  9. DatePicker

  10. Image

More components will be provided in the future.

Text Components

Heading

This is the top level title of a page.

ParameterDescription
type
(required)
string
"TextHeading"
text
(required)
string
Dynamic "${data.text}"
visible
Boolean
Dynamic "${data.is_visible}"
Default: True

Subheading

ParameterDescription
type
(required)
string
"TextSubheading"
text
(required)
string
Dynamic "${data.text}"
visible
Boolean
Dynamic "${data.is_visible}"
Default: True

Body

ParameterDescription
type
(required)
string
TextBody
text
(required)
string
Dynamic "${data.text}"
font-weight
enum
{'bold','italic','bold_italic','normal'}
Dynamic "${data.font_weight}"
strikethrough
Boolean
Dynamic "${data.strikethrough}"
visible
Boolean
Dynamic "${data.is_visible}"
Default: True

Caption

ParameterDescription
type
(required)
string
"TextCaption"
text
(required)
string
Dynamic "${data.text}"
font-weight
enum
{'bold','italic','bold_italic','normal'}
Dynamic "${data.font_weight}"
strikethrough
Boolean
Dynamic "${data.strikethrough}"
visible
Boolean
Dynamic "${data.is_visible}"
Default: True

Limits and Restrictions

Component Type Limit / Restriction

Heading

Subheading

Body

Caption

Character Limit

80

80

4096

4096

Heading

Subheading

Body

Caption

Text

Empty or Blank value is not accepted

For comparison purposes, we show how the text components look like next to one another:

Text Entry Components

TextInput

ParameterDescription
type
(required)
string
"TextInput"
label
(required)
string
Dynamic "${data.label}"
input-type
enum
{'text','number','email', 'password', 'passcode', 'phone'}
required
Boolean
Dynamic "${data.is_required}"
min-chars
String
Dynamic "${data.min_chars}"
max-chars
String
Dynamic "${data.max_chars}".
Default value is 80 characters.
helper-text
String
Dynamic "${data.helper_text}"
name
(required)
String
visible
Boolean
Dynamic "${data.is_visible}"
Default: True

TextArea

ParameterDescription
type
(required)
string
"TextArea"
label
(required)
string
Dynamic "${data.label}"
required
Boolean
Dynamic "${data.is_required}"
max-length
String
Dynamic "${data.max_length}"
Default value is 600 characters.
name
(required)
String
helper-text
String
Dynamic "${data.helper_text}"
enabled
Boolean
Dynamic "${data.is_enabled}"
visible
Boolean
Dynamic "${data.is_visible}"
Default: True

Limits and Restrictions

Component Type Limit / Restriction

TextInput

Helper Text

Error Text

Label

80 characters

30 characters

20 characters

TextArea

Helper Text

Label

80 characters

20 characters

Together, the text entry components look like as shown:

CheckboxGroup

CheckboxGroup component allows users to pick multiple selections from a list of options.

ParameterDescription
type
(required)
string
"CheckboxGroup"
data-source
(required)
Array < id: String, title: String, description: String, metadata: String, enabled: Boolean>
Dynamic "${data.data_source}"
name
(required)
String
min-selected-items
Integer
Dynamic "${data.min_selected_items}"
max-selected-items
Integer
Dynamic "${data.max_selected_items}"
enabled
Boolean
Dynamic "${data.is_enabled}"
label
string
Dynamic "${data.label}"
required
Boolean
Dynamic "${data.is_required}"
visible
Boolean
Dynamic "${data.is_visible}"
Default: True
on-select-action
Action
Only `data_exchange` is supported.

Example

For the data-source field, you can declare it dynamically or statically.

Static Example

This static example hardcodes the respective id's and title's for the data-source field.

Dynamic Example

In this dynamic example, you can see that data-source references the days_per_week_options of type array defined before it using days_per_week_options. When defining such a structure, you need to specify items in the array, which will be of type object. Then inside the items object, you have a properties dictionary with id and title just like in the static declaration. Both id and title will always be of type String. Within the days_per_week_options array, you must define concrete examples in the __example__ field.

Limits and Restrictions

Type Limit / Restriction

Label Content

Title

Description

Metadata

Min # of options

Max # of options

30 Characters

30 Characters

300 Characters

20 Characters

1

20

RadioButtonsGroup

ParameterDescription
type
(required)
string
"RadioButtonsGroup"
data-source
(required)
Array < id: String, title: String, description: String, metadata: String, enabled: Boolean>
Dynamic "${data.data_source}"
name
(required)
String
enabled
Boolean
Dynamic "${data.is_enabled}"
label
(required)
string
Dynamic "${data.label}"
required
Boolean
Dynamic "${data.is_required}"
visible
Boolean
Dynamic "${data.is_visible}"
Default: True
on-select-action
Action
Only `data_exchange` is supported.

Example

For the data-source field, you can declare it dynamically or statically.

Static Example

This static example hardcodes the respective id's and title's for the data-source field.

Dynamic Example

In this dynamic example, you can see that data-source references the experience_level_options of type array defined before it using data.experience_level_options. When defining such a structure, you need to specify items in the array, which will be of type object. Then inside the items object, you have a properties dictionary with id and title just like in the static declaration. Both id and title will always be of type String. Within in the experience_level_options array you must define concrete examples in the __example__ field.

Limits and Restrictions

Type Limit / Restriction

Label Content

Title

Description

Metadata

Min # of options

Max # of options

30 Characters

30 Characters

300 Characters

20 Characters

1

20

ParameterDescription
type
(required)
string
"Footer"
label
(required)
string
Dynamic "${data.label}"
left-caption
String
Dynamic "${data.left_caption}"

Can set left-caption and right-caption or only center-caption, but not all 3 at once

center-caption
String
Dynamic "${data.center_caption}"

Can set center-caption or left-caption and right-caption, but not all 3 at once

right-caption
String
Dynamic "${data.right_caption}"

Can set right-caption and left-caption or only center-caption, but not all 3 at once

enabled
Boolean
Dynamic "${data.is_enabled}"
on-click-action
(required)
Action
Action

Limits and Restrictions

Type Limit / Restriction

Label Max Character Limit

Captions Max Character Limit

35

15

OptIn

ParameterDescription
type
(required)
string
"OptIn"
label
(required)
string
Dynamic "${data.label}"
required
Boolean
Dynamic "${data.is_required}"
name
(required)
String
on-click-action
Action
Action that is executed on clicking "Read more".

"Read more" is only visible when an on-click-action is specified.

visible
Boolean
Dynamic "${data.is_visible}"
Default: True

Example

Limits and Restrictions

Type Limit / Restriction

Content Max Character Limit

Max number of Opt-Ins Per Screen

120

5

Dropdown

ParameterDescription
type
(required)
string
"Dropdown"
label
(required)
string
data-source
(required)
Array < id: String, title: String, enabled: Boolean, description: String, metadata: String >
Dynamic "${data.data_source}"
required
Boolean
enabled
Boolean
Dynamic "${data.is_enabled}"
required
Boolean
Dynamic "${data.is_required}"
visible
Boolean
Dynamic "${data.is_visible}"
Default: True
on-select-action
Action
Only `data_exchange` is supported.

Example


Limits and Restrictions

Type Limit / Restriction

Label

Title

Min dropdown options

Max dropdown options

Description

Metadata

20 characters

30 characters

1

200

300 characters

20 characters

For the data-source field, you can declare it dynamically or statically.

Static Example

This static example hardcodes the respective id's and title's for the data-source field.

Dynamic Example

In this dynamic example, you can see that data-source references the experience_level_options of type array defined before it using experience_level_options. When defining such a structure, you need to specify items in the array, which will be of type object. Then inside the items object, you have a properties dictionary with id and title just like in the static declaration. Both id and title will always be of type String. Within the experience_level_options array you must define concrete examples in the __example__ field.

Limits and Restrictions

Type Limit / Restriction

Label

Title

Min dropdown options

Max dropdown options

20 characters

30 characters

1

200

Embedded Link

ParameterDescription
type
(required)
string
"EmbeddedLink"
text
(required)
string
Dynamic "${data.text}"
on-click-action
(required)
Action
Action
visible
Boolean
Dynamic "${data.is_visible}"
Default: True

Limits and Restrictions

Type Limit / Restriction

Character limit

25

Case

Sentence case

Max Number of Embedded Links Per Screen

2

Text

Empty or Blank value is not accepted

DatePicker

The DatePicker component allows users to input dates through an intuitive date selection interface.

Currently, the DatePicker doesn't support scenarios where the business and the end user are in different time zones. We recommend only using the component if you plan to send your Flows to users in a specific timezone. For details, please refer to section Guidelines for Usage
ParameterDescription
type
(required)
string
"DatePicker"
label
(required)
string
Dynamic "${data.label}"
min-date
String (timestamp in milliseconds)
Dynamic "${data.min_date}". Please refer to section Guidelines for Usage
max-date
String (timestamp in milliseconds)
Dynamic "${data.max_date}". Please refer to section Guidelines for Usage
name
(required)
string
unavailable-dates
Array < timestamp in milliseconds: String >
Dynamic "${data.unavailable_dates}". Please refer to section Guidelines for Usage
visible
Boolean
Dynamic "${data.is_visible}"
Default: True
helper-text
String
Dynamic "${data.helper_text}"
enabled
Boolean
Dynamic "${data.is_enabled}"
Default: True
on-select-action
Action
Only `data_exchange` is supported.

Payload that is sent to a data channel business endpoint is a string which shows the timestamp in milliseconds.


Guidelines for Usage

Due to current system limitations, the DatePicker functions correctly and as intended(that is, correct selection range is shown to the User, and accurate user-selection value is returned to the Business) as long as

  • The guidelines in this section are followed
  • Both the business sending the Flow and its end-users are in the same time zone.

Correct behavior is not guaranteed if businesses and end-users are in different time zones. For example, if a business operating in Sao Paulo (UTC-3) sends a Flow to a user in Manaus (UTC-4), the DatePicker may not work as expected. We don't recommend using it if your users are in different time zones than you.

Handling of Dates for Businesses and Users in the Same Time Zone

DatePicker allows setting of date range for user selection through min-dates and max-dates fields, and also prevents selection of specific dates using the unavailable-dates field. If you have not supplied the date range , then by default, the component allows the user to select dates from 1 January 1900 to 31 December 2100.

Setting Date Parameters in the Component

When you specify the date range or set unavailable dates, you should convert your local dates with midnight (00:00:00) as a base time to UTC timestamps.

For example, if you are a business based in India who wants to collect a date in the range 21 March 2024 to 25 March 2024, then you should set min-dates and max-dates as 1710958020000 and 1711303620000, respectively.

21 March 2024, 00:00:00.000 IST converts to 20 March 2024, 18:30:00.000 UTC which is represented by timestamp 1710958020000.

25 March 2024, 00:00:00.000 IST converts to 24 March 2024, 18:30:00.000 UTC which is represented by timestamp 1711303620000.

Component Integration

DatePicker will read the timestamps in min-dates, max-dates and unavailable-dates fields and convert it to the end user's local date for displaying on the UI. In the example we discussed above, a user in India will see dates from 21 March 2024 to 25 March 2024 in the DatePicker component.

Processing User Selection

Businesses will receive a UTC timestamp, which should be converted back to the business's local time zone. Importantly, businesses should focus solely on the date portion of the resulting timestamp , disregarding the time portion. This ensures that the date remains consistent with the user's selection. Unfortunately, this conversion will only work correctly when the business and user are in the same time zone.

For example, if you receive a timestamp 1711013400000 then convert it to your local timezone and extract the date. If you are in IST, the timestamp will convert to 21 March 2024 15:00 IST, and you should treat 21st March 2024 as the user selected date.

Recommendation for navigating Time Zone differences

If you need to send flow messages to users in time zones different from yours despite reviewing the above guidelines, follow these steps to overcome the limitation:

  • If you are a business based in Brazil and want to serve flows to your users across the country, then your time zone range will be UTC-2 (Fernando de Noronha) to UTC-5 (Rio Branco).
  • Add a Dropdown component within your Flow that allows users to select their current time zone.
  • Identify the westernmost time zone from your time zone range. In our example, it is UTC-5.
  • Provide the dates you want to collect in the westernmost time zone, using midnight as the reference time. For example, if you want to collect dates from March 20th, 2024 to March 25th, 2024, then provide the timestamp in milliseconds for March 20th, 2024 at 5 AM UTC and March 25th, 2024 at 5 AM UTC.
  • Convert the timestamps received from the user to their respective time zone and use the corresponding date. For example, if a user is in Sao Paulo(UTC-3) and you receive a timestamp of 1710910800000, then convert it to UTC-3 to get March 20th, 2024.

Limits and Restrictions

Type Limit / Restriction

Label Max Length

40 characters

Helper Text Max Length

80 characters

Error Message Max Length

80 characters

Image

ParameterDescription
type
(required)
string
"Image"
src
(required)
string
Base64 of an image.
Dynamic "${data.src}"
width
Integer
Dynamic "${data.width}"
height
Integer
Dynamic "${data.height}"
scale-type
string
`cover` or `contain`
Default value: `contain`
aspect-ratio
Number
Default value: 1
Dynamic "${data.aspect_ratio}"
alt-text
string
Alternative Text is for the accessibility feature, eg. Talkback and Voice over
Dynamic "${data.alt_text}"

Image Scale Types

Scale Type Description

cover

Image is clipped to fit the image container.

If there is no height value (which is the default), the image will be displayed to its full width with its original aspect ratio.

If the height value is set, the image is cropped within the fixed height. Depending on the image whether it is portrait or landscape, image is clipped vertically or horizontally.

contain

Image is contained within the image container with the original aspect ratio.

If there is no height value (which is the default), the image will be displayed to its full width with its original aspect ratio.

If the height value is set, the image is contained in the image container with the fixed height and the original aspect ratio.

Developers should consider setting a specific height, width and aspect ratio for images whenever using contain. On Android devices WhatsApp sets a default height value of 400, which may create some unwanted spacing.

Example


Limits and Restrictions

Type Limit / Restriction

Max number of images per screen

Recommended image size

Total data channel payload size

Supported images formats

3

Up to 300kb

1 Mb

JPEG PNG

Dynamic components

Here's a corrected version:

If you check the attribute model of certain components (Dropdown, DatePicker, RadioGroup and CheckboxGroup), you will find that some of them accept the on-xxxx-action attribute. This attribute allows the component to trigger a data-exchange action. It can be used in the following scenarios:

  1. When a user selects a date in the DatePicker component.
  2. When the business needs to fetch available data (such as table slots, tickets, etc.) for this selected date by calling a data_exchange action.
  3. Once the data is received, the user will see an updated screen with new data.

Prerequisites

The following steps require communication between the client and the business server. Please ensure that you have configured the data channel before attempting to use this feature.

Step 1 - Defining the layout

Let's begin with a minimal example, consisting of an empty form and a CTA button, and gradually add more components.

So, we want to build a simple form that takes a date and displays the list of available time slots. First, we'll add a DatePicker component:

Next step is to add a Dropdown where we will display all available timeslots:

Step 2 - Defining 3P Data

Until now, we've been incorporating static mock data, but now we aim to connect a screen with dynamic data. Dynamic data can originate from various sources:

  1. Initial message payload
  2. navigate - transitioning from the previous screen using a navigate action
  3. data_exchange - a request to the business server

In this example, we'll assume that the data will come from a data_exchange request. So, let's instruct Flow JSON to use the data channel request by providing the "data_api_version": "3.0" property.

Step 3 - Allowing DatePicker to Make a Request to the Server

Let's provide "on-select-action" to the DatePicker component so we can execute the call to the business server. In the payload, we can pass any data we want to the business server to understand the type of request.

{
   "on-select-action":{
      "name":"data_exchange",
      "payload":{
         "date":"${form.date}",
         "component_action":"update_date"
      }
   }
}

In this example, we'll send the value of the field date to the action payload, and we'll also add some static data "component_action": "update_date" to help the server recognize the type of request. There is no strict format here; you can choose whatever works for your case.

Now when you try to select a date, a data_exchange request will be executed. The server may return the data that can change the UI. For now, our Flow doesn't expect or use any data from the server. Let's fix it by first defining the data model that we expect for a screen.

Step 4 - Define a Server Data Model

Let's declare a data property for the screen outlining the data that we expect to receive from the server. So, we want to receive an available_slots array with timeslot options.

It should have the following model. The __example__ field is mock data used to display the data within the web preview.

{
    "available_slots": {
        "type": "array",
        "items": {
            "type": "object",
            "properties": { "id": {"type": "string"}, "title": {"type": "string"} }
        },
        "__example__": [ {"id": "1", "title": "08:00"}, {"id": "2", "title": "09:00"} ]
    }
}

It means that the expected payload to be returned from server can look like the following:

{
    "version": "3.0",
    "screen": "BOOKING",
    "data": {
       "available_slots": [ {"id": "1", "title": "08:00"}, {"id": "2", "title": "09:00"} ]
    }
}

So you Flow JSON now should look like the following:

Step 5 - Control Visibility of the Component

Now, when we select a date in DatePicker, the application will send a request to the business server to get available timeslots. However, we don't want a Dropdown to be visible until there is data to display. How can we hide it?

For this purpose, we can use the visible attribute on Dropdown and connect it with server data. The business server can control the visibility of the component based on a set condition.

So, we need to make the following changes:

  1. Define is_dropdown_visible in the data model of the screen.
  2. Connect a property via dynamic binding "visible": "${data.is_dropdown_visible}".
  3. Ensure that the server returns the correct data.

Let's update our code:

NOTE: The current version of the playground doesn't support endpoint requests

Summary

That's it! Now you have a dynamic component set up. If you're facing any challenges, feel free to ask a question on the developer forum. We'll be happy to help!