io.select.multiple

Several choices, listed one per row.

io.select.multiple asks to pick several options. The drop-down sits on top and every pick gets a row under it. The × on a row takes the pick back. The handler gets the chosen options themselves, records from your database included.

The simplest one

The whole action file, and roughly what your team sees when it runs.

src/actions/orders/notifyDelayAction.ts
import { app } from '../../app';
export const notifyDelayAction = app.defineAction({
name: 'Notify delay',
handler: async ({ io }) => {
const channels = await io.select.multiple('Notify by', {
options: ['Email', 'Slack', 'SMS'],
defaultValue: ['Email'],
});
},
});
The code. One call in an action, the whole file.
tools.example.com/actions/orders/notify_delay

Notify delay

Notify by
Add…▾
Email×
Continue
In the browser. Roughly what your team sees. Your theme decides the details.

What you can set

The settings you will reach for most, each with the line of code that turns it on.

io.select.multiple('Notify by', { options })

One row per pick. Each chosen option is listed under the drop-down. The × on its right takes it back.

options: ['Email', 'Slack', 'SMS']

Only what is left. The drop-down offers the options not chosen yet. Nothing can be picked twice.

label: (user) => user.email

Records from your database. key says what identifies each record and label what the list shows. The handler gets the records back.

defaultValue: ['email']

Picked at the start. defaultValue takes the options or just their keys. Ids from your records are enough.

minSelections: 1, maxSelections: 2

A minimum and a maximum. minSelections asks for at least so many. At maxSelections the drop-down stops offering more.

// channels is [Email, SMS]

In the order of the options. The handler gets the picks in the order you passed the options. The order they were clicked does not matter.

io.select.multiple(…).optional()

Optional when you say so. Nothing picked counts as empty. With .optional() the handler gets undefined for it.

// Notify by: choose at most 2.

Checked on the server. Too few, too many or a value that was not offered is sent back. The message shows under the field.

.validate((channels) => message)

Checks of your own. .validate() gets the chosen options on the server. Return a message and the person picks again.

Write your first tool today.

An async function, a few await calls, and the form is in the browser.

AwaitIO is free for small teams, made possible by companies and people who sponsor it.