io.select.table
Prompts the app user to select any number of values from an array of tabular data.
Usage
- TypeScript
- JavaScript
- Python
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,
},
],
});
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,
},
],
});
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,
},
],
)
Props
- TypeScript
- JavaScript
- Python
columns
Optional
(string | object)[]
accessorKey
Optional
string
label
Required
string
renderCell
Optional
(row: T) => string | object
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[]
defaultPageSize
Optional
number
disabled
Optional
boolean
helpText
Optional
string
initiallySelected
OptionalNew in 1.4.0
(row: T) => boolean
isFilterable
Optional
boolean
isSortable
Optional
boolean
maxSelections
Optional
number
minSelections
Optional
number
rowMenuItems
OptionalNew in 0.25.0
(row: T) => object[]
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[]
columns
Optional
(string | object)[]
accessorKey
Optional
string
label
Required
string
renderCell
Optional
(row: T) => string | object
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[]
defaultPageSize
Optional
number
disabled
Optional
boolean
helpText
Optional
string
initiallySelected
OptionalNew in 1.4.0
(row: T) => boolean
isFilterable
Optional
boolean
isSortable
Optional
boolean
maxSelections
Optional
number
minSelections
Optional
number
rowMenuItems
OptionalNew in 0.25.0
(row: T) => object[]
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[]
columns
Optional
Iterable[TableColumn | str]
PrimitiveValue = str | int | float | bool | date | time | datetime
class ImageSchema(TypedDict):
url: NotRequired[str]
alt: NotRequired[str]
size: NotRequired[Literal["thumbnail", "small", "medium", "large"]]
class TableRow(TypedDict):
label: NotRequired[PrimitiveValue]
value: NotRequired[PrimitiveValue]
url: NotRequired[str]
route: NotRequired[str]
params: NotRequired[Mapping[str, PrimitiveValue]]
highlightColor: NotRequired[Literal["red", "orange", "yellow", "green", "blue", "purple", "pink", "gray"]]
image: NotRequired[ImageSchema]
class TableColumn(TypedDict, T):
label: str
renderCell: NotRequired[(T) -> TableRow | PrimitiveValue]
accessorKey: NotRequired[str]
data
Optional
Iterable[T]
default_page_size
Optional
int
disabled
Optional
bool
help_text
Optional
str
is_filterable
Optional
bool
is_sortable
Optional
bool
max_selections
Optional
int
min_selections
Optional
int
row_menu_items
Optional
(TableRow) -> MenuItem
PrimitiveValue = str | int | float | bool | date | time | datetime
class ImageSchema(TypedDict):
url: NotRequired[str]
alt: NotRequired[str]
size: NotRequired[Literal["thumbnail", "small", "medium", "large"]]
class TableRow(TypedDict):
label: NotRequired[PrimitiveValue]
value: NotRequired[PrimitiveValue]
url: NotRequired[str]
route: NotRequired[str]
params: NotRequired[Mapping[str, PrimitiveValue]]
highlightColor: NotRequired[Literal["red", "orange", "yellow", "green", "blue", "purple", "pink", "gray"]]
image: NotRequired[ImageSchema]
class MenuItem(TypedDict):
label: str
theme: NotRequired[Literal["danger"]]
disabled: NotRequired[bool]
route: NotRequired[str]
params: NotRequired[Mapping[str, PrimitiveValue]]
url: NotRequired[str]
initially_selected
OptionalNew in 1.4.0
(TableRow) -> bool
Returns
list[TableRow]
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.
- TypeScript
- JavaScript
- Python
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"],
});
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"],
});
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.
- TypeScript
- JavaScript
- Python
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,
}),
},
],
});
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,
}),
},
],
});
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": lambda row: {
f"{row['first_name'] {row['last_name']}"
},
},
{
"label": "Phone number",
"accessorKey": "phone_number",
},
{
"label": "Photo",
"renderCell": lambda row: {
"image": {
"url": row.image,
"alt": f"{row.first_name} {row.last_name} profile photo",
"size": "small",
},
},
},
{
"label": "Website",
"renderCell": lambda 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.
- TypeScript
- JavaScript
- Python
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}`,
},
],
});
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}`,
},
],
});
selected = await io.select.table(
"Albums",
data=albums,
columns=["album", "artist", "year"],
row_menu_items=lambda row: [
{
"label": "Edit metadata",
"action": "edit_album",
"params": { "id": row['id'] },
},
{
"label": "Listen on Spotify",
# external URLs automatically open in a new tab.
"url": f"https://open.spotify.com/album/{row['spotifyId']}",
},
],
)