Links

Widgets in Forms

Field Widgets empower your Actions Forms providing various options to display inputs and ease operators in their daily operations.

Widgets

Widget
Supported types
Minimal version
Description
null
All types
@forestadmin/agent@*
Use the default widget
String
@forestadmin/[email protected]
Display a text input with address autocomplete.
Checkbox
Boolean
@forestadmin/[email protected]
Display a checkbox with true/false and possibly null values.
StringList, NumberList
@forestadmin/[email protected]
Display a group of checkboxes to select multiple values.
String
@forestadmin/[email protected]
Display a color picker to select a color.
Number
@forestadmin/[email protected]
Display a currency input.
Date, Dateonly, String
@forestadmin/[email protected]
Display a calendar date picker
Dropdown
Date, Dateonly, Number, String, StringList
@forestadmin/[email protected]
Users can choose between a limited set of values.
Json
@forestadmin/[email protected]
Display a Json editor with syntax highlighting.
Number
@forestadmin/[email protected]
Display a standard number input.
NumberList
@forestadmin/[email protected]
Display a standard number input to enter a list of number values.
Date, Dateonly, Number, String
@forestadmin/[email protected]
Group of radio buttons to choose a value from.
RichText
String
@forestadmin/[email protected]
Rich text area allowing to input formatted text.
TextArea
String
@forestadmin/[email protected]
Multi-line text area.
TextInput
String
@forestadmin/[email protected]
One-line text input.
StringList
@forestadmin/[email protected]
One-line text input to enter a list of string values
Time
@forestadmin/[email protected]
Input for entering a time
String, StringList
@forestadmin/[email protected]
Dropdown containing the users available in the current project

Address autocomplete widget

The address autocomplete widget allows to input an address as a text value, autocompleted by the Google Maps API.
agent.customizeCollection('customer', collection => {
collection.addAction('Update address', {
scope: 'Single',
form: [
{
label: 'Address',
type: 'String',
widget: 'AddressAutocomplete',
placeholder: 'Type the address here',
},
],
execute: async context => {
/* ... perform work here ... */
},
});
});
The above code will produce the following form (when empty):
Address autocomplete widget on an action form (empty)
And once the user starts typing:
Address autocomplete widget on an action form (with suggestions)

Options

Option
Type
Usage
Minimal version
Description
placeholder
string
optional
@forestadmin/[email protected]
Placeholder shown in the component.

Checkbox widget

The checkbox widget allows to activate or deactivate a boolean value.
agent.customizeCollection('product', collection => {
collection.addAction('Refresh price', {
scope: 'Single',
form: [
{
label: 'Send a notification',
type: 'Boolean',
widget: 'Checkbox',
isRequired: true,
defaultValue: false,
},
],
execute: async context => {
/* ... perform work here ... */
},
});
});
The above code will produce the following form:
Checkbox widget on an action form

Options

The Checkbox widget has no specific options, but its behavior can be customized using the following already existing options on fields:
Option
Type
Usage
Minimal version
Description
defaultValue
boolean or null
optional
@forestadmin/agent@*
Default value of the field. Define a value different from null in combination to isRequired to receive a not-null value even if the user did not click the widget.
isRequired
boolean
optional
@forestadmin/agent@*
If isRequired is set to false (default value), the checkbox widget allows users to choose between 3 states: true, false and null. Setting isRequired to true only allows 2 states: true and false. In both cases the default value will be null if not defined.
By default, the Checkbox widget allows 3 states:
  • null
  • true
  • false
To ensure having only 2 states, you need to:
  1. 1.
    set the isRequired option to true,
  2. 2.
    define a value for the defaultValue option.

Checkbox group widget

The checkbox group widget allows to select multiple values from a list of options.
agent.customizeCollection('product', collection => {
collection.addAction('Leave a review', {
scope: 'Single',
form: [
{
label: 'Why do you like this product?',
type: 'StringList',
widget: 'CheckboxGroup',
options: [
{ value: 'price', label: 'Good price' },
{ value: 'quality', label: 'Build quality' },
{ value: 'look', label: 'It looks good' },
],
},
],
execute: async context => {
/* ... perform work here ... */
},
});
});
The above code will produce the following form:
Checkbox group widget on an action form

Options

Option
Type
Usage
Minimal version
Description
options
An array if values, an array of value/label pairs, or a function receiving a context object returning this shape.
required
@forestadmin/[email protected]
List of available options in the component. Supported formats:
  • ['Good', 'Very good']
  • [{value: 2, label: 'Good'}, {value: 3, label: 'Very good'}]
  • (context) => ['Good', 'Very good']
  • (context) => [{value: 2, label: 'Good'}, {value: 3, label: 'Very good'}]

Color picker widget

The color picker widget allows to select a color.
organization.addAction('Customize UI', {
scope: 'Single',
form: [
{
label: 'Background color',
type: 'String',
widget: 'ColorPicker',
placeholder: 'Select the color',
isRequired: true,
enableOpacity: false,
quickPalette: [
'#6002ee',
'#90ee02',
'#021aee',
'#d602ee',
'#ee0290',
'#ee6002',
],
},
],
execute: () => {},
});
The above code will produce the following form:
Color picker widget on an action form

Options

Option
Type
Usage
Minimal version
Description
enableOpacity
boolean
optional
@forestadmin/[email protected]
Allow users to select a color with an opacity.
placeholder
string
optional
@forestadmin/[email protected]
Placeholder shown in the component.
quickPalette
string
optional
@forestadmin/[email protected]
List of colors to display in the quick palette. The list can be an array of hex colors or rgba colors.

Currency input widget

The currency input widget allows to input a currency value.
agent.customizeCollection('product', collection => {
collection.addAction('Change price', {
scope: 'Single',
form: [
{
label: 'Price',
type: 'Number',
widget: 'CurrencyInput',
placeholder: 'Enter the new price',
isRequired: true,
min: 0,
max: 1000,
step: 1,
currency: 'USD',
base: 'Unit',
},
],
execute: async context => {
/* ... perform work here ... */
},
});
});
The above code will produce the following form:
Currency input widget on an action form

Options

Option
Type
Usage
Minimal version
Description
currency
string or a function returning a string (dynamic forms).
required
@forestadmin/[email protected]
Currency code to display in the component. Valid currency ISO codes ↗ is required.
base
Unit (default value) or Cent
optional
@forestadmin/[email protected]
Base unit to use for the value.unitValue is expressed in the currency's base unit.centValue is expressed as a hundredth of the base unit (typically in cents).
min
number or a function returning a number (dynamic forms).
optional
@forestadmin/[email protected]
Minimum value allowed.
max
number or a function returning a number (dynamic forms).
optional
@forestadmin/[email protected]
Maximum value allowed.
placeholder
string
optional
@forestadmin/[email protected]
Placeholder shown in the component.
step
number or a function returning a number (dynamic forms).
optional
@forestadmin/[email protected]
Step between two values.

DatePicker widget

The date picker widget allows to input a date in a form
agent.customizeCollection('order', collection => {
collection.addAction('Set shipping date', {
scope: 'Single',
form: [
{
label: 'Shipping date',
type: 'Date',
widget: 'DatePicker',
format: 'DD-MM-YYYY',
min: new Date(Date.now() - 10 * 24 * 60 * 60 * 1000),
max: new Date(),
placeholder: 'please indicate when you shipped the item',
},
],
execute: async context => {
/* ... perform work here ... */
},
});
});
The above code will produce the following form :
Date input on an action form
Note: using a Dateonly field type will hide the time section from the date picker

Options

Option
Type
Usage
Minimal version
Description
format
string or function returning a string
optional
@forestadmin/[email protected]
The date picker uses moment.js library under the hood. You can refer to this documentation ↗ to specify your date display format
placeholder
string
optional
@forestadmin/[email protected]
Text will be shown as placeholder if the field is empty
min
Date or function returning a Date
optional
@forestadmin/[email protected]
The minimum date allowed to be set in the field
max
Date or function returning a Date
optional
@forestadmin/[email protected]
The maximum date allowed to be set in the field
The dates are sent as ISO 8601 formatted strings over the network. In order to use them as Date object in your hooks, you can parse them directly like so
const shippingDate = new Date(context.formValues['Shipping date']))
The dropdown widget allows to select a value from a list of options.
agent.customizeCollection('product', collection => {
collection.addAction('Leave a review', {
scope: 'Single',
form: [
{
label: 'Rating',
type: 'Number',
widget: 'Dropdown',
options: [
{ value: 0, label: 'Poor' },
{ value: 1, label: 'Fair' },
{ value: 2, label: 'Good' },
{ value: 3, label: 'Very good' },
{ value: 4, label: 'Excellent' },
],
search: 'disabled',
placeholder: 'Select a rating',
isRequired: true,
},
],
execute: async context => {
/* ... perform work here ... */
},
});
});
The above code will produce the following form:
Dropdown widget on an action form
In this next example, we call a remote api to get a list of products and then perform a custom filter based on given fields of the json response, and return the first 25. This example uses search: 'dynamic' dropdown widget, which provides you with the searchValue in the callback context.
Note: when a search is performed, only the field on which it is performed will have its options recomputed.
agent.customizeCollection('product', collection => {
collection.addAction('Add more products', {
execute: async (context, resultBuilder) => {
// ...
},
scope: 'Bulk',
form: [
{
label: 'Select some products',
type: 'StringList',
widget: 'Dropdown',
search: 'dynamic',
options: async (context, searchValue) => {
const products = await (
await fetch('https://api.fake-eshop.com/v2/products')
).json();
return products
.filter(product => {
return (
!searchValue ||
['description', 'name', 'features', 'keyword', 'category'].some(
key =>
product[key]?.toLowerCase().includes(searchValue.toLowerCase()),
) ||
// Here we also provide any previously selected products so as not to loose their
// labels on frontend side
context.formValues['Select some products']?.some(
alreadySelectedValue => product.id === alreadySelectedValue,
)
);
})
.slice(0, 25)
.sort((a, b) => a.name.localeCompare(b.name))
.map(product => ({ label: product.name, value: product.id }));
},
},
],
});
});

Options

Option
Type
Usage
Minimal version
Description
options
Either an array of values, or an array of value/label pairs, or a function returning one of those arrays
required
@forestadmin/[email protected] (@forestadmin/[email protected] for dynamic options)
List of available options in the component. Supported formats:
  • ['Good', 'Very good']
  • [{value: 2, label: 'Good'}, {value: 3, label: 'Very good'}]
placeholder
string
optional
@forestadmin/[email protected]
Placeholder shown in the component.
search
static, dynamic or disabled(default)
optional
@forestadmin/[email protected], dynamic available from @forestadmin/[email protected]
Allow users to input text to filter values displayed in the dropdown. - disabled: Users need to scroll to find the appropriate option. - static: Users can search a value by typing terms in an input. The search will be done in the browser, based on the label. - dynamic The search is performed on the agent side, using any custom logic needed to fetch the required options

Number input widget

The number input widget allows to input a number value.
agent.customizeCollection('product', collection => {
collection.addAction('Change price', {
scope: 'Single',
form: [
{
label: 'Price',
type: 'Number',
widget: 'NumberInput',
placeholder: 'Enter the new price',
isRequired: true,
min: 0,
max: 1000,
step: 1,
},
],
execute: async context => {
/* ... perform work here ... */
},
});
});
The above code will produce the following form:
Number input widget on an action form

Options

Option
Type
Usage
Minimal version
Description
min
number or a function returning a number (dynamic forms).
optional
@forestadmin/[email protected]
Minimum value allowed.
max
number or a function returning a number (dynamic forms).
optional
@forestadmin/[email protected]
Maximum value allowed.
placeholder
string
optional
@forestadmin/[email protected]
Placeholder shown in the component.
step
number or a function returning a number (dynamic forms).
optional
@forestadmin/[email protected]
Step between two values.

JSON editor widget

The JSON editor widget display a rich editor with syntax highlighting for JSON.
agent.customizeCollection('product', collection => {
collection.addAction('Set properties', {
scope: 'Single',
form: [
{
label: 'Properties',
type: 'Json',
widget: 'JsonEditor',
defaultValue: { color: 'red' },
},
],
execute: async context => {
/* ... perform work here ... */
},
});
});
The above code will produce the following form:
JSON editor widget on an action form

Options

This widget does not have any options.

Number input list widget

The number input list widget allows to input a list of number values.
agent.customizeCollection('product', collection => {
collection.addAction('Change step values', {
scope: 'Single',
form: [
{
label: 'Step values',
type: 'NumberList',
widget: 'NumberInputList',
placeholder: 'Enter the new step value',
isRequired: true,
min: 0,
max: 1000,
step: 1,
},
],
execute: async context => {
/* ... perform work here ... */
},
});
});
The above code will produce the following form (once the user entered two step values):
Number input list widget on an action form

Options

Option
Type
Usage
Minimal version
Description
allowDuplicates
boolean
optional
@forestadmin/[email protected]
Allow users to enter duplicate values.
allowEmptyValues
boolean
optional
@forestadmin/[email protected]
Allow users to enter empty values.
enableReorder
boolean
optional
@forestadmin/[email protected]
Allow users to reorder values.
min
number
optional
@forestadmin/[email protected]
Minimum value allowed.
max
number
optional
@forestadmin/[email protected]
Maximum value allowed.
placeholder
string
optional
@forestadmin/[email protected]
Placeholder shown in the component.
step
number
optional
@forestadmin/[email protected]
Step between two values.

Radio group widget

The radio group widget allows to select a value from a list of options.
agent.customizeCollection('product', collection => {
collection.addAction('Leave a review', {
scope: 'Single',
form: [
{
label: 'Appreciation',
type: 'Number',
widget: 'RadioGroup',
options: [
{ value: 1, label: 'Good' },
{ value: 0, label: 'Average' },
{ value: -1, label: 'Bad' },
],
},
],
execute: async context => {
/* ... perform work here ... */
},
});
});
The above code will produce the following form:
Radio group widget on an action form

Options

Option
Type
Usage
Minimal version
Description
options
An array if values, an array of value/label pairs, or a function receiving a context object returning this shape.
required
@forestadmin/[email protected]
List of available options in the component. Supported formats:
  • ['Good', 'Very good']
  • [{value: 2, label: 'Good'}, {value: 3, label: 'Very good'}]
  • (context) => ['Good', 'Very good']
  • (context) => [{value: 2, label: 'Good'}, {value: 3, label: 'Very good'}]
Using the options function, you can dynamically change the list of options based on the context, which contains information about the selected records and other values in the form. More info about dynamic configuration.

Rich text widget

The rich text widget allows to input a formatted text value.
agent.customizeCollection('product', collection => {
collection.addAction('Leave a review', {
scope: 'Single',
form: [
{
label: 'Comment',
type: 'String',
widget: 'RichText',
isRequired: true,
placeholder: 'Type your comment here',
},
],
execute: async context => {
/* ... perform work here ... */
},
});
});
The above code will produce the following form:
Rich text widget on an action form

Options

Option
Type
Usage
Minimal version
Description
placeholder
string
optional
@forestadmin/[email protected]
Placeholder shown in the component.