Skip to main content
Big news! Interval has been acquired by Meter. Learn more →

io.select.table

Prompts the app user to select any number of values from an array of tabular data.

Usage

const albums = await io.select.table("Select your favorites", {
data: [
{
album: "Exile on Main Street",
artist: "The Rolling Stones",
year: 1972,
},
{
artist: "Michael Jackson",
album: "Thriller",
year: 1982,
},
{
album: "Enter the Wu-Tang (36 Chambers)",
artist: "Wu-Tang Clan",
year: 1993,
},
],
});
interval.com

Props

columns

Optional

(string | object)[]

Optional array of column definitions. If not provided, the object keys will be used.

accessorKey

Optional

string

Column accessor key. At least one of `accessorKey` or `renderCell` must be specified.

label

Required

string

Column header label.

renderCell

Optional

(row: T) => string | object

Function that receives the row as argument and returns either a string value, or an object for advanced customization. See the function definition below for available properties. At least one of `renderCell` or `accessorKey` must be specified.
renderCell: (row: T) => string | {
// the visible cell label
label: string | number | boolean;
// an optional underlying value for sorting
value?: string | number | boolean;
// links the cell's contents to an external URL
url?: string;
// links the cell's contents to another action or page
route?: string;
// arbitrary key/value pairs to send to the linked route
params?: Record<string, any>;
// highlight color for the cell, will affect text color and background color
highlightColor?: "red" | "orange" | "yellow" | "green" | "blue" | "purple" | "pink" | "gray"
// a visible image to be displayed in the cell
// must contain either `url` or `buffer`
image?: {
// a URL to the image
url?: string
// a buffer containing the image contents
buffer?: Buffer
// the image alt tag
alt?: string
// the size of the image
size?: "thumbnail" | "small" | "medium" | "large"
}
}

data

Required

T[]

Array of possible values to be selected. Values are objects with arbitrary keys/values.

defaultPageSize

Optional

number

The default page size for the paginated table. Pass `Infinity` to disable pagination by default.

disabled

Optional

boolean

Whether selection is disabled for rows within the table.

helpText

Optional

string

Secondary label providing additional context for the selection. Supports inline markdown elements like bold, italics, and links.

initiallySelected

OptionalNew in 1.4.0

(row: T) => boolean

If set, returns whether the row will be initially selected when shown to the user.

isFilterable

Optional

boolean

Whether to show a text input alongside the table for filtering and searching through rows. Defaults to `true`.

isSortable

Optional

boolean

Whether to allow sorting by column. Defaults to `true`.

maxSelections

Optional

number

Maximum number of selected values accepted for submission.

minSelections

Optional

number

Minimum number of selected values required for submission, defaults to 0.

rowMenuItems

OptionalNew in 0.25.0

(row: T) => object[]

If set, returns an array of items to display in a dropdown menu next to each row.
rowMenuItems: (row: T) => {
// the visible menu item label
label: string;
// links the menu item to an external URL
url?: string;
// links the menu item to another action or page
route?: string;
// arbitrary key/value pairs to send to the linked route
params?: Record<string, any>;
// disables the menu item
disabled?: boolean
// the style of the item
theme?: 'danger' | undefined
}[]

Returns

T[]

Examples

Customizing output

The default behavior shown above is to display all of the fields in each record. To customize the display of records, a columns property can be provided. The columns property can contain an array of data property names, and only those columns will be displayed in the table.

await io.select.table("Users", {
data: [
{
email: "carsta.rocha@example.com",
phone_number: "(60) 1416-4953",
birthdate: "1993-08-04",
first_name: "Carsta",
last_name: "Rocha",
image: "https://example.com/photos/21351234.jpg",
website_url: "https://example.com",
},
{
email: "irene.morales@example.org",
phone_number: "625-790-958",
birthdate: "1982-04-28",
first_name: "Irene",
last_name: "Morales",
image: "https://example.com/photos/8321527.jpg",
website_url: "https://example.org",
},
],
columns: ["first_name", "last_name", "email"],
});

The columns array can also contain definition objects, with a label property and either an accessorKey string or a renderCell callback that returns a primitive value or object with optional label and value primitive values, url or route, and highlightColor string properties, and optional params and image object properties.

info

The label property (and plain string return value shorthand) supports markdown, though markdown links will be omitted if used alongside the route or url properties.

await io.select.table("Users", {
data: [
{
email: "carsta.rocha@example.com",
phone_number: "(60) 1416-4953",
birthdate: "1993-08-04",
first_name: "Carsta",
last_name: "Rocha",
image: "https://example.com/photos/21351234.jpg",
website_url: "https://example.com",
},
{
email: "irene.morales@example.org",
phone_number: "625-790-958",
birthdate: "1982-04-28",
first_name: "Irene",
last_name: "Morales",
image: "https://example.com/photos/8321527.jpg",
website_url: "https://example.org",
},
],
columns: [
{
label: "Name",
renderCell: row => `${row.first_name} ${row.last_name}`,
},
{
label: "Phone number",
accessorKey: "phone_number",
},
{
label: "Photo",
renderCell: row => ({
image: {
url: row.image,
alt: `${row.first_name} ${row.last_name} profile photo`,
size: "small",
},
}),
},
{
label: "Birth date",
renderCell: row => {
const [y, m, d] = row.birthdate.split("-").map(s => Number(s));
const birthDate = new Date(y, m - 1, d);
return {
label: birthDate.toLocaleDateString(),
value: birthDate,
};
},
},
{
label: "Website",
renderCell: row => ({
label: row.website_url,
url: row.website_url,
}),
},
],
});

If the renderCell callback returns a route property, a link will be generated to the action with that slug. A params object can also be defined, this object will be passed to the action's ctx.params context value.

tip

The two forms shown above can be combined within a single columns definition.

Adding menus

Beginning with SDK v0.25.0, each row can be given a dropdown menu using the rowMenuItems property, a function that provides the current row as the only argument and returns an array of menu items.

const selected = await io.select.table("Albums", {
data: albums,
columns: ["album", "artist", "year"],
rowMenuItems: row => [
{
label: "Edit metadata",
route: "edit_album",
params: { id: row.id },
},
{
label: "Listen on Spotify",
// external URLs automatically open in a new tab.
url: `https://open.spotify.com/album/${row.spotifyId}`,
},
],
});
interval.com
Did this section clearly explain what you wanted to learn?