io.select.table
Prompts the app user to select any number of values from an array of tabular data.
Usage
- TypeScript
- JavaScript
- Python Experimental
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 Experimental
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>;
// 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
isFilterable
Optional
boolean
isSortable
Optional
boolean
maxSelections
Optional
number
minSelections
Optional
number
rowMenuItems
Optional
(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>;
// 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
isFilterable
Optional
boolean
isSortable
Optional
boolean
maxSelections
Optional
number
minSelections
Optional
number
rowMenuItems
Optional
(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]]
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]]
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]
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 Experimental
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 an object with optional label
, value
, url
, action
string properties, and optional params
and image
object properties.
- TypeScript
- JavaScript
- Python Experimental
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 an action
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 Experimental
const selected = await io.select.table("Albums", {
data: albums,
columns: ["album", "artist", "year"],
rowMenuItems: row => [
{
label: "Edit metadata",
action: "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",
action: "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']}",
},
],
)