io.select.table

Pick rows straight from a table.

io.select.table shows records as a table with a radio or a checkbox in front of each row. The person picks one row or several. The handler gets the picked records themselves, every field included. The table has the same filter, pager and columns as io.display.table.

The simplest one

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

src/actions/users/resetPasswordAction.ts
import { app } from '../../app';
import { prisma } from '../../db';
export const resetPasswordAction = app.defineAction({
name: 'Reset password',
handler: async ({ io }) => {
const [user] = await io.select.table('User', {
data: await prisma.user.findMany(),
columns: ['name', 'email'],
});
},
});
The code. One call in an action, the whole file.
tools.example.com/actions/users/reset_password

Reset password

UserFilter
name
Ana Ruiz
Ben Carter
Mia Chen
Omar Haddad
Lena Fischer
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.

const [user] = await io.select.table(…)

One row by default. Every row gets a radio and one must be picked. The handler gets it in a list.

maxSelections: 50

Checkboxes for several. Raise maxSelections and the radios turn into checkboxes. A pick past the limit is ignored.

data: await prisma.device.findMany()

The records come back. Pass rows as your query returns them. The handler gets the same objects, dates and relations included.

columns: ['name', { label, renderCell }]

Columns like the display table. Name a key, or build a cell from the whole record with renderCell.

pageSize: 25

Filter and paging. A filter above the table and a pager under it, both in the browser. Ten rows a page unless you say otherwise.

defaultValue: [owner]

Picked at the start. defaultValue takes items of data. Copies with the same values work too.

emptyText: 'This account has no devices.'

Nothing to pick. With no rows, the person sees emptyText and continues. The handler gets an empty list.

// User: pick a row.

Checked on the server. The browser answers only with the positions of the picked rows. Too few, too many or a row that was not in the table is sent back.

.validate((rows) => message)

Checks of your own. .validate() gets the picked rows 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.