# Edit widgets

This page walks you through all available *edit* widgets settings.

{% hint style="info" %}
For an introduction on what widgets are and a comprehensive list of what widgets you'll be able to choose from, check out the previous page: [Customize your fields](https://docs.forestadmin.com/user-guide/~/revisions/meYmZqO8vH8noaQkmIkl/collections/customize-your-fields)
{% endhint %}

## Text input

Content inputting in its most basic form, the *Text input* is quite what you will find in most online forms.\
For more advanced or specialized content types, see the other widgets.

## Textarea

Much like the *Text input*, the *Textarea* widget is more appropriate when inputting longer portions of text.\
To input formatted content, check out the *Rich text editor* below.

## Rich text editor

This widget is what you need when handling formatted text. You will be able to decorate your text in **bold**, *italic* and much more.

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-b7a77467d74e9e0406517d034b73d2f9c1627f69%2Fimage.png?alt=media)

## Price editor

This widget is perfect for editing prices, thanks to a real-time preview of what the formatted number will look like:

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-1b88f78d71284e0181a21d2aed58542ea412c888%2Fimage.png?alt=media)

To set up your widget:

* Choose a currency symbol between **euros** (EUR), **dollars** (USD) and **pounds** (GBP)
* Choose a base: **Cents** if your values are stored in cents, **Unit** otherwise

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-2ab3fc73eb299f7d129d38647cfd10e530ebcee0%2Fimage.png?alt=media)

{% hint style="info" %}
The **number formatting** is based on your browser's locale, unless you have a specific [locale](https://docs.forestadmin.com/user-guide/~/revisions/meYmZqO8vH8noaQkmIkl/project-settings/general-tab#locale) set in your Project settings.
{% endhint %}

## Dropdown

The dropdown is a very powerful and customizable widget. As you would expect, the result will be a dropdown which allows you to choose between several values.

However, you can customize it in the following ways:

### Static

Use *Static* content type if you want to manually enter your content.

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-084c310961bbcf59c8d30b3e0bbd8ff90a25d10f%2Fimage.png?alt=media)

Your values should be added **manually** - as a comma-separated list -, **unless** you enabled the *Alter values* option (available in [display settings](https://docs.forestadmin.com/user-guide/~/revisions/meYmZqO8vH8noaQkmIkl/collections/customize-your-fields/..#display-settings)) or if your field is an enum, in which cases you will be able to simply enable/disable values to add them:

!["Alter values" option (display settings)](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-19e39256cb05153c0e7582d8d699cb87dd743804%2Fimage.png?alt=media)

![If "Alter values" enabled or field is an enum](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-0869f09046f9e584d4b16fa037685ccf8761bd54%2Fimage.png?alt=media)

### Dynamic

Use this option if you want your content to depend dynamically on your data:

*Simple mode*

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-be450916eef5691009c9295326c6f71a5da91961%2Fimage.png?alt=media)

In *Simple mode*, just select which collection you wish to select values from for your dropdown. You can optionally add a filter.

*Dynamic mode*

In Dynamic mode, values will be fetched from your own API endpoint. Here's an example:

{% tabs %}
{% tab title="SQL" %}
![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-4ac43ce965345e0bd6a969068bb4c982e554ff53%2FScreenshot%202019-04-09%20at%2011.48.31.png?alt=media)

{% code title="app.js" %}

```javascript
'use strict';
var express = require('express');
var app = express();
var fs = require('fs');

// ...

// You MUST require these files before the default routes.
fs.readdirSync('./decorators/routes').forEach((file) => {
  if (file[0] !== '.') {
    app.use('/forest', require(`./decorators/routes/${file}`));
  }
});

fs.readdirSync('./routes').forEach((file) => {
  if (file[0] !== '.') {
    app.use('/forest', require('./routes/' + file));
  }
});

app.use(require('forest-express-sequelize').init({
  modelsDir: __dirname + '/models',
  envSecret: process.env.FOREST_ENV_SECRET,
  authSecret: process.env.FOREST_AUTH_SECRET,
  sequelize: require('./models').sequelize
}));

module.exports = app;
```

{% endcode %}

{% code title="decorators/routes/orders.js" %}

```javascript
// Configure the dropdown in dynamic mode using this path: /forest/orders/shippingStatusOptions
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-sequelize');

// This is a simple case but you can retrieve your data from an external API or using your own logic
const data = [
  'Being processed',
  'Ready for shipping',
  'In transit',
  'Shipped',
  'Failed',
];

router.get('/orders/shippingStatusOptions', Liana.ensureAuthenticated, (req, res) => {
  res.send({ data });
});

module.exports = router;
```

{% endcode %}

![The five status are displayed in the drop-down menu.](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-cb07a5ebbf859ff9e0a51d01db0fc56cbc26ffee%2FScreenshot%202019-04-09%20at%2012.42.21.png?alt=media)

{% hint style="info" %}
You can add more logic by retrieving the record id or the record type using `request.context.record.id, request.context.record.type`
{% endhint %}

In the example below, the dropdown will only suggest status according to the current status of the order.

{% code title="decorators/routes/orders.js" %}

```javascript
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-sequelize');
const models = require('../../models');

const STATUS_OPTION_DEFAULT = 'Being processed';
const STATUS_TRANSITIONS = {
  'Being processed': ['Ready for shipping'],
  'Ready for shipping': ['In transit'],
  'In transit': ['Shipped', 'Failed'],
};

router.get('/orders/shippingStatusOptions', Liana.ensureAuthenticated, async (req, res) => {
  const { context } = req.query;
  const recordId = context && context.record && context.record.id;
  let data = [STATUS_OPTION_DEFAULT];

  if (recordId) {
    const order = await models.orders.findById(recordId);
    const currentShippingStatus = order.shippingStatus;
    if (STATUS_TRANSITIONS[currentShippingStatus]) {
      data = STATUS_TRANSITIONS[currentShippingStatus];
    }
  }
  res.send({ data });
});

module.exports = router;
```

{% endcode %}

![Only specific status are displayed based on the previous status of the record.](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-f8ba5c124e7ee479ee549bdaa688a5db5ae5db38%2FScreenshot%202019-04-09%20at%2012.44.02.png?alt=media)
{% endtab %}

{% tab title="Mongodb" %}
![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-4ac43ce965345e0bd6a969068bb4c982e554ff53%2FScreenshot%202019-04-09%20at%2011.48.31.png?alt=media)

{% code title="app.js" %}

```javascript
'use strict';
var express = require('express');
var app = express();
var fs = require('fs');

// ...

// You MUST require these files before the default routes.
fs.readdirSync('./decorators/routes').forEach((file) => {
  if (file[0] !== '.') {
    app.use('/forest', require(`./decorators/routes/${file}`));
  }
});

fs.readdirSync('./routes').forEach((file) => {
  if (file[0] !== '.') {
    app.use('/forest', require('./routes/' + file));
  }
});

app.use(require('forest-express-mongoose').init({
  modelsDir: __dirname + '/models',
  envSecret: process.env.FOREST_ENV_SECRET,
  authSecret: process.env.FOREST_AUTH_SECRET,
  mongoose: require('mongoose')
}));

module.exports = app;
```

{% endcode %}

{% code title="decorators/routes/orders.js" %}

```javascript
// Configure the dropdown in dynamic mode using this path: /forest/orders/shippingStatusOptions

const express = require('express');
const router = express.Router();
const Liana = require('forest-express-mongoose');

// This is a simple case but you can retrieve your data from an external API or using your own logic
const data = [
  'Being processed',
  'Ready for shipping',
  'In transit',
  'Shipped',
  'Failed',
];

router.get('/orders/shippingStatusOptions', Liana.ensureAuthenticated, (req, res) => {
  res.send({ data });
});

module.exports = router;
```

{% endcode %}

![The five status are displayed in the drop-down menu.](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-cb07a5ebbf859ff9e0a51d01db0fc56cbc26ffee%2FScreenshot%202019-04-09%20at%2012.42.21.png?alt=media)

{% hint style="info" %}
You can add more logic by retrieving the record id or the record type using `request.context.record.id, request.context.record.type`
{% endhint %}

In the example below, the dropdown will only suggest status according to the current status of the order.

{% code title="decorators/routes/orders.js" %}

```javascript
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-mongoose');
const Order = require('../../models/orders');

const STATUS_OPTION_DEFAULT = 'Being processed';
const STATUS_TRANSITIONS = {
  'Being processed': ['Ready for shipping'],
  'Ready for shipping': ['In transit'],
  'In transit': ['Shipped', 'Failed'],
};

router.get('/orders/shippingStatusOptions', Liana.ensureAuthenticated, async (req, res) => {
  const { context } = req.query;
  const recordId = context && context.record && context.record.id;
  let data = [STATUS_OPTION_DEFAULT];

  if (recordId) {
    const order = await Order.findById(recordId);
    const currentShippingStatus = order.shippingStatus;
    if (STATUS_TRANSITIONS[currentShippingStatus]) {
      data = STATUS_TRANSITIONS[currentShippingStatus];
    }
  }
  res.send({ data });
});

module.exports = router;
```

{% endcode %}

![Only specific status are displayed based on the previous status of the record.](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-f8ba5c124e7ee479ee549bdaa688a5db5ae5db38%2FScreenshot%202019-04-09%20at%2012.44.02.png?alt=media)
{% endtab %}
{% endtabs %}

### Relationship

If your field refers to another collection, the dropdown option will automatically populate the data of that collection.\
\
In this example, an **order** `belongs to` a **product**. In **order**'s field settings, you'll find:

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-0b9a0d62463919354d3c2e1e31e0fe6b0eb9248c%2Fimage.png?alt=media)

While creating a new order, all products are available in the dropdown:

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-bac19e1e1dfa63918ebbe79d679923aa16ab0a61%2Fimage.png?alt=media)

You can also **add one or more filters** to display only a dataset of the associated collection.

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-42ef0de5a61cb37adfea8506f331c6eb5cc281e0%2Fimage.png?alt=media)

In this case, only Star Wars products will be available in the dropdown:

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-ca0220550c136b7c6dde34de6ff57f70b5c098cf%2Fimage.png?alt=media)

### Enable search

Say you have a *long list* of options to choose from. A dropdown becomes a bit *cumbersome*: this is why we've added this option.

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-fa9235e5ffba7c68f25c94ea706c1e189d57d88f%2Fimage.png?alt=media)

When enabled, the widget becomes an auto-complete input dropdown.

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-6f40d299e5968c98bb080c5634c8b863e02d238f%2Fimage.png?alt=media)

## Radio button

The radio button widget works the same way as the [dropdown](#dropdown) widget: depending on your field type and whether you used the Alter values option (available in [display settings)](https://docs.forestadmin.com/user-guide/~/revisions/meYmZqO8vH8noaQkmIkl/collections/customize-your-fields/..#display-settings), you will have to manually enter your values or simply toggle them.

![Manually entering values](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-4f4b4f21cc7e07b6d8c92a9db6e381e24fc94e36%2Fimage.png?alt=media)

!["Alter values" option (display settings)](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-7c5abffb63c5261fce59bbfdd4279a8f2ea6c91d%2FCapture%20d%E2%80%99e%CC%81cran%202020-12-01%20a%CC%80%2015.15.45.png?alt=media)

While editing, the widget will look like this:

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-aa29eb85d30471ecd11fa96d379efbec0364d82b%2Fimage.png?alt=media)

## Checkboxes

The checkboxes widget works the same way as the [dropdown](#dropdown) widget: depending on your field type and whether you used the Alter values option (available in [display settings)](https://docs.forestadmin.com/user-guide/~/revisions/meYmZqO8vH8noaQkmIkl/collections/customize-your-fields/..#display-settings), you will have to manually enter your values or simply toggle them.

![Manually entering values](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-739af792856f32f7380fca2b31f8965ceb3abc4c%2Fimage.png?alt=media)

!["Alter values" option (display settings)](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-f91fc871b848851f26df3368a948e675a0b4b21d%2FCapture%20d%E2%80%99e%CC%81cran%202020-12-01%20a%CC%80%2015.17.17.png?alt=media)

While editing, your widget will look like this:

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-c43c219b82b929a7023abb8fbeebfeef71202eed%2Fimage.png?alt=media)

## File picker

Use this widget to upload files (images, pdf,..). This can be done by clicking on the grey rectangle or drag & drop'ing your file in the grey rectangle.

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-40141e971b683c24edd689f5c22919ba4b105a13%2Fimage.png?alt=media)

### Settings

In your field's settings, you may set the following:

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-70ffbf41ee4f398a17919e8fee5b24bcae2ee53e%2Fimage.png?alt=media)

* *Specific file extensions:* restrict which file types your users may upload
* *Maximum file size*: set a maximum weight for your files
* *Prefix*: indicate a path to preview your saved files when editing. More on this option [here](https://docs.forestadmin.com/user-guide/~/revisions/meYmZqO8vH8noaQkmIkl/collections/display-widgets#prefix).

### Edit tools

The File picker widget looks like this:

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-6cc193539b1744cc5899aef4b65777d04ae54982%2Fimage.png?alt=media)

When uploading a single image, it allows you to perform 2 basic operations before *using this file*:

* Rotate
* Crop (adjust your image's borders until it fit a desired area)

### Upload multiple files at once

For fields accepting multiple files, a new setting is available: setting a maximum number of files.

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-6ae8e35e724c598c8ea36bd5d1daedba1ef19623%2Fimage.png?alt=media)

When uploading multiple files at once, your widget will look like this. Note that uploading multiple files at once will prevent you from using the *rotate* and *crop* features.

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-130295659bb679e93903d6224bca282baa0fe9ae%2Fimage.png?alt=media)

In the above picture, the *Use these files* button will become available after removing the first file by clicking the red cross icon.

### Large files upload

If you need to upload large files, you may need to add some code to allow it. Check out [this paragraph](https://docs.forestadmin.com/woodshop/how-tos/import-data-from-a-csv-file#uploading-large-files).

### Date picker

Use this widget if your content is a date.

![To validate these date and time, click outside of the widget](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-a40a4c698604d5ba44fa5952c3ab743dc19868e5%2Fimage.png?alt=media)

{% hint style="info" %}
Depending on your field type, this might be a *Dateonly picker* widget.
{% endhint %}

### Color picker

Use this widget if your content is a color.

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-b55f2b34e305fe6d097678e8d79df9f032a64896%2Fimage.png?alt=media)

### JSON editor

Use this widget to handle JSON content.

![](https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-b712a0364d0ac6a046d43eaa12fade05f27a2ead%2Fimage.png?alt=media)

## Address

This widget allows you to benefit from [Google Places](https://developers.google.com/maps/documentation/places/web-service)'s address autocompletion.

<figure><img src="https://85223878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOx0Wo3NZjrQrGQthTy6o%2Fuploads%2Fgit-blob-c78eff4288a359d19c5f8dc221fcae7d67dddf15%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="danger" %}
The full address will be put in a single field (in our above example: *description*)
{% endhint %}

## User dropdown

This widget allows you to input the email address of a user of the current project.\
You may search for a user using their firstname, lastname or email address.

{% hint style="info" %}
The user can then be efficiently displayed using the [User](https://docs.forestadmin.com/user-guide/collections/customize-your-fields/display-widgets#user) *display* widget.\
\
Both widgets work together to make **record assignment** easily achievable.
{% endhint %}
