Fields
Select Field
The select field renders a dropdown menu in the admin UI. In single mode it stores a string, and in multi-select mode it stores a string[]. Each option generates a v.literal() validator, combined with v.union() to form a type-safe enum. Use it for statuses, categories, tags, and any field with a fixed set of choices.
Config options
| Option | Type | Default | Description |
|---|---|---|---|
required | boolean | false | Makes the field required in both the schema and the admin UI. |
options * | Array<string | { label: string; value: string }> | — | The available choices. Can be plain strings or label/value objects. |
multiple | boolean | false | Allow selecting more than one option. Stores an array instead of a single value. |
readOnly | boolean | false | Renders the select as disabled. |
placeholder | string | — | Placeholder text shown when no option is selected. |
label | string | (data) => string | Auto-generated | Custom label for the admin UI. |
description | string | — | Help text displayed below the label. |
condition | FieldCondition | — | Conditionally show or hide this field. |
sidebar | boolean | false | Place this field in the document sidebar. |
listColumn | boolean | false | Show as a default column in list views. |
Example usage
import { f, defineVextroCollection } from "vextro";
export const articles = defineVextroCollection({
slug: "articles",
label: "Articles",
collectionType: "content",
tableName: "articles",
fields: {
title: f.text({ required: true }),
status: f.select({
required: true,
options: ["draft", "published", "scheduled", "trashed"],
sidebar: true,
sidebarSection: "document",
listColumn: true,
listColumnWidth: "small",
}),
category: f.select({
options: [
{ label: "News & Updates", value: "news" },
{ label: "Tutorials", value: "tutorial" },
{ label: "Case Studies", value: "case-study" },
],
placeholder: "Choose a category...",
}),
tags: f.select({
options: ["featured", "trending", "editors-pick", "breaking"],
multiple: true,
description: "Select one or more tags.",
}),
},
}); Admin behavior
In single mode, the select field renders a custom dropdown component. In multi-select mode (multiple: true), it renders a multi-select input that displays selected values as removable pills. Options defined as { label, value } objects display the label in the UI while storing the value in the database.
Convex validator mapping
The validator is built from the options array. For a single select with options ["draft", "published"], the generated validator is v.union(v.literal("draft"), v.literal("published")). For multi-select, it wraps that union in v.array().
Conditional display
archiveReason: f.select({
options: ["outdated", "duplicate", "off-topic", "other"],
required: true,
condition: { field: "status", equals: "trashed" },
}), When a condition is set, the field is always optional in the Convex schema regardless of the required setting.