-
Notifications
You must be signed in to change notification settings - Fork 6
Forms
The forms feature allows sending interactive forms as part of a regular text message. When a user submits the form, the formSubmission
event is raised containing the form data.
Posting a form is done by including the form
attribute as part of content of the addTextItem
and updateTextItem
APIs.
Only one form per message is allowed. The form will be rendered after any text content as shown in the F1 Bot example above. The form will be highlighed by a left bar.
Forms can be updated using the updateTextItem
API. To remove a form call updateTextItem
with a form attribute that only has its id
attribute defined.
The limit in the number of controls in a form is defined by the maximum size of the text item payload.
Only buttons trigger a form submission.
// Post a form
const item = await client.addTextItem(convId, {
content: 'Fill out the form to register a complaint',
form: {
id: 'myform1234',
title: 'Complaint Form',
controls: [{
type: Circuit.Enums.FormControlType.INPUT,
name: 'issue',
text: 'Describe the problem',
rows: 3
}, {
type: Circuit.Enums.FormControlType.BUTTON,
text: 'Send'
}]
});
// Update the form
await client.updateTextItem({
itemId: item.itemId,
content: 'Do you want to submit aonther complaint?',
form: {
id: 'myform1234',
controls: [{
type: Circuit.Enums.FormControlType.BUTTON,
name: 'followup',
options: [{
text: 'Another one?',
value: 'more'
}, {
text: `I'm done`,
value: 'done'
}]
}]
}
});
// Remove the form, and update the text message
await client.updateTextItem({
itemId: item.itemId,
content: 'Have a nice day.',
form: {
id: 'myform1234'
}];
});
The event formSubmission
is raised whenever a user submits a form. Adding an event listener for the event is required as for all other events. Only the creator of the form will get the event. The event data includes the submitters userId and the form values.
A participant may submit the form multiple times. It is the responsibility of the app handling the submission to ingnore subsequent submission if needed.
Every conversation participant sees the same state of the form. That means if the app updates the form after a submission (e.g. remove the submit button), then all users will see that change. For direct conversations it may make sense to update the form based on the submission, but in group conversation less so.
client.addEventListener('formSubmission', evt => {
const { type, itemId, form, submitterId } = evt;
const { id, data } = form;
console.log(`user ${submittedId} posted form ${id}`);
data.forEach(ctrl => console.log(`${ctrl.key}: ${ctrl.value}`));
});
Forms are usually submitted by the official Circuit clients. The SDK can also submit forms with the API submitForm
.
The form.data
array is identical to what the formSubmission
event will receive.
await client.submitForm(item.itemId, {
id: 'form1234',
data: [{
key: 'issue',
value: 'My PC is frozen'
}]
});
The form object is made up of an id
, an optional title
and an array of controls
.
-
id
is of typestring
and used to identify the a particular form received in theformSubmission
event - [
title
] is of type string and displayed at the top of the form -
controls
is an array ofFormControl
s
Note: Brackets indicates attribute is optional.
The supported form controls are defined with enum Circuit.Enums.FormControlType:
-
INPUT
: Input textfield. One or multiple rows -
RADIO
: List radio elements to select a single value from -
CHECKBOX
: Single or group of checkboxes -
DROPDOWN
: Dropdown list with multiple values -
BUTTON
: Single or multiple buttons -
LABEL
: Text label -
SPACER
: Separating of controls
Unless otherwise specified, all controls have the attributes:
-
type
: Type of control as shown above with enumCircuit.Enums.FormControlType
. -
name
: Name of the control. Applicable to submittable controls (input, radio, checkbox, dropdown). Use to identify the control in the `formSubmission event. - [
title
]: Text shown above the control.
Renders an input element with one or more rows.
Additional attributes:
- [
text
]: Placeholder text - [
rows
]: Number of rows. If more than 1, rendered as textarea DOM element in browser. - [
size
]: Width of element. Possible values are small (25%), medium (50%) and large (100%). If more than 1 row, defaults to large, otherwise medium.
Example:
{
type: 'INPUT',
name: 'feedback',
text: 'Please provide your feedback', // optional
rows: 3, // optional, defaults to 1
size: 'large' // 'large' is already the default multi-row inputs
}
Renders a radio button set.
Additional attributes:
- [
defaultValue
]: Value of radio button select by default. -
options
: Array ofFormOption
s. Each option defines a single radio button.-
text
: Radio button text -
value
: Radio button value of type string
-
Example:
{
type: 'RADIO',
name: 'champion',
title: 'Who is the current F1 World Champion?', // optional
defaultValue: '5', // optional
options: [{
text: 'Vettel',
value: '5'
}, {
text: 'Hamilton',
value: '44'
}, {
text: 'Alonso',
value: '14'
}]
}
Renders a single checkbox or a set of checkboxes as single control. For set of checkboxes the options
attribute is used. Defining options
with a single element is identical to defining a checkbox without the options
array.
Additional attributes:
- [
text
]: Checkbox button text. Only for single checkbox. - [
value
]: Checkbox button value of type string. So values are 'true' or 'false'. Only for single checkbox. - [
defaultValue
]: If set to 'true', then checkbox is selected by default. - [
options
]: Array ofFormOption
s. Each option defines a single checkbox. Only for set of checkboxes.-
text
: Checkbox button text -
value
: Checkbox button value of type string. - [
defaultValue
]: If set to 'true', then checkbox is selected by default.
-
Examples:
// single checkbox
{
type: 'CHECKBOX',
name: 'usa_race',
title: 'Is there an F1 race in the USA in 2018?',
text: 'Yes',
defaultValue: 'true'
}
// set of checkboxes
{
type: 'CHECKBOX',
name: 'active_drivers',
title: 'Which are active F1 drivers?', // optional
options: [{ // required for multi select
text: 'Sebastian Vettel',
value: 'vet',
defaultValue: 'true' // optional
}, {
text: 'Charles Leclerc',
value: 'lec'
}, {
text: 'Ayrton Senna',
value: 'sen'
}]
}
Renders a dropdown control. Dependent dropdowns (where the values of a dropdown control depend on the selection of another dropdown control) is not supported.
Selecting a dropdown value does not trigger a form submission.
Additional attributes:
- [
defaultValue
]: Value of dropdown selected by default. -
options
: Array ofFormOption
s. Each option defines an entry in the dropdown.-
text
: Dropdown item text -
value
: Dropdown item value
-
Example:
{
title: 'Which is the first race of the 2018 season?',
type: 'DROPDOWN',
name: 'first_race',
defaultValue: 'spa', // optional
options: [{
text: 'Spa',
value: 'spa'
}, {
text: 'Monaco',
value: 'monaco'
}, {
text: 'Melbourne',
value: 'australia',
}]
}
Renders a single button, or a button set. Clicking any button triggers a form submission.
A button set may be used for a voting form instead of radio buttons with a submit button.
Additional attributes:
-
text
: Button text - [
action
]: Action for a single button. Suported actions are:-
submit
: submits a form (default) -
reset
: resets a form to its initial state -
submit_reset
: submits a form and then resets form to initial state
-
- [
notification
]: Notification message shown to user when performing an action (clicking a button) - [
options
]: Array ofFormOption
s. Each option defines a button.-
text
: Button text -
value
: Button value. Used to identify which button has been clicked.
-
Example:
// Single button with text 'Send' default action of 'submit'
{
type: 'BUTTON',
text: 'Send'
}
// Submit and reset buttons
{
type: 'BUTTON',
options: [{
text: 'Submit',
action: 'submit',
notification: 'Form submitted successfully'
}, {
text: 'Cancel',
action: 'reset'
}]
}
// Multiple buttons used for voting (i.e. not other form controls)
{
type: 'BUTTON',
name: 'fruit',
options: [{
text: 'Apple',
value: '1'
}, {
text: 'Banana asd asd asd asdsa das asd',
value: '2'
}, {
text: "Strawberry",
value: '3'
}]
}
Renders a text label. Text may contain Circuit text formatting such as bold, italic or even a link.
'Thank you ...' text in image above is a label.
Label controls don't contain a value, so the name
attribute is not applicable. So the only attributes are the type
and text
.
Additional attributes:
-
text
: Label text
Example:
{
type: 'LABEL',
text: '<b>Total</b>: Apple (0) - Banana (3) - Strawberry (1)'
}
Adds extra space between controls. May be used for grouping of controls.
Spacer controls don't contain any attributes other than the type itself.
Example:
{
type: 'SPACER'
}
REST API (swagger)
The REST API also supports sending forms and register webhooks for form submissions.
An example using the REST API to post forms and handle their submissions is the Trivia Game example. See code for form posting and webhook registration and webook handling