Skip to main content

Forms in notifications

You can create forms in notifications to request information from users. Forms can be as simple or complex as your workflows require. The information users provide is passed back to your calling application when the user submits the form. Your app subscribes to form-related events to provide custom error handling and to get the form data to process.

How it works

The form property is available in the "custom" template and the "markdown" template. The same form field types and widget types are available in both.

A form object is an array of fields. Each field specifies the data type of the form field and the widget that specifies the type of form field. The following widget types are available:

  • "Checkbox". Data type "boolean"

  • "CheckboxGroup". Data type "checkboxGroup"

  • "Date". Data type "date"

  • "Dropdown". Data type "string"

  • "Number". Data type "number"

  • "RadioGroup". Data type "radioGroup"

  • "Text". Data type "string". Supports a text area with the multiline property

  • "Time". Data type "time"

  • "Toggle". Data type "boolean"

Validation

A form field can include optional validation. Validation rules are specific to each data type. Each rule provides standard error strings if validation fails, or you can provide a custom string with the invalidMessage value.

The DateField, RadioGroupField, CheckboxGroupField, and TimeField widgets support only the required validation rule. For available validation rules for other form fields, see the API reference for each field.

You can also write custom validation rules by monitoring the notification-form-values-changed event and including the setErrors method on the event object. See the API reference for this event, and the example on this page for a simple custom validation rule.

If any validation rule fails, the user cannot submit the form.

Submit and process the form

The entire form requires a button that includes the submit: true and cta: true properties. A button.formOptions property lets you specify different button text for different states of the form. See the API reference for ButtonOptions. For information about monitoring different form states, see the section in this article on subscribing to form-related events.

How to do it

Create the form

The following example includes a markdown template, but the same form definition could be used with a custom template. This example shows how to add different form fields. It is not intended to provide a real-world example. Some fields are included to help show how to write custom error handling.

const orderRequestForm: NotificationOptions = 
{
template: "markdown",
toast: "sticky",
title: "Form Example",
indicator:
{
color: "purple"
text: "EXAMPLE"
},
icon: "LOGO.png",
form:
{
// whether required fields are marked as required in the notification
displayFieldRequirementStatus: true,
fields:
// array of form fields
[
// Dropdown form field
{
// key value is included in form events
key: "buy_option",
// label for the form field
label: "Order Type",
// data type
type: "string",
// widget object config
widget: {
type: "Dropdown",
options: [
{
label: "Option One",
value: "option_one"
},
{
label: "Option Two",
value: "option_two"
}
]
}
},
// Number form field
{
key: "share_quantity",
label: "Share Quantity",
type: "number",
widget: {
type: "Number",
min: 100
}
},
// Number form field with optional currencyChar property
// See API reference for other optional properties
{
key: "share_price",
label: "Share Price",
type: "number",
widget: {
type: "Number",
currencyChar: "$"
}
},
{
// Text form field with simple validation
key: "notes",
label: "Notes",
type: "string",
widget:
{
type: "Text",
placeholder: "Add notes here",
multiline: true,
rows: 4
},
validation:
{
max:
{
arg: 256,
invalidMessage: "Cannot be more than 256 characters"
}
}
},
{
// Text form field with custom validation
key: "sourceEmail",
type: "string",
label: "Email",
helperText: "We will use this email to send you the report after we crawl your website",
widget:
{
type: "Text"
},
validation:
{
required:
{
arg: true
}
}
}
],
}
buttons: [
{
title: "Submit",
iconUrl: "favicon.ico",
submit: true,
// for custom validation errors, you can also specify an errorTitle value
formOptions: { submittingTitle: "Submitting Form ...", successTitle: "Submitted" }
}
]
};

To process the form, at a minimum you subscribe to the notification-form-submitted event type so your app can handle the form data.

addEventListener("notification-form-submitted", (event: NotificationFormSubmittedEvent) => 
{
// example logs to console, but your app would process the form data as needed
console.log(`Form submitted: ${JSON.stringify(event.form)}`);
});

Here event.form is a Record, where key values are specified in the form definition, and field values are the values submitted by the user.

The default behavior is for the notification to be dismissed when it is submitted. You can also add the preventDefault and formStatus methods to your event handler. See the API reference for these methods. These methods let you monitor the status of the form submission if you provide values for the formOptions property when you define the form.

You can also subscribe to the notification-form-values-changed event to provide custom error handling. The following example validates the Email text field specified in the form definition example.

const addEmailPhoneValidation = () => {
addEventListener(
'notification-form-values-changed',
async (formValueChanged: NotificationFormValuesChangedEvent) => {
const errors = [];

// Simple regular expression to check for a valid email address
const emailPattern = /^\S+@\S+\.\S+$/;

// Field to validate
const email = formValueChanged.form.sourceEmail as string;

// Validate email if it's not null or undefined
if (email && !emailPattern.test(email)) {
errors.push({
fieldKey: 'sourceEmail',
error: 'Invalid email format'
});
}

// If there are any errors, set them all at once
if (errors.length > 0) {
await formValueChanged.setErrors(errors);
}
}
);
};

Best practices

  • You can’t require that a user must submit a form, because the user can always dismiss the notification. Consider including an ‘ignore’ or ‘cancel’ button, so the user doesn’t have to hunt for the close button.

  • Make sure any custom validation messages (invalidMessage property) are clear, so the user knows exactly what is expected of them.