obsidian/wiki/payloadcms/fields-select.md
2026-05-15 15:37:03 +01:00

5.2 KiB

title aliases tags sources created updated
Select Field
select-field
multi-select
dropdown-field
payloadcms
fields
select
enum
dropdown
raw/fields__select.md
2026-05-15 2026-05-15

Dropdown-style field storing one or many values from a predefined list. Backed by a database enum (Postgres) or string field.

Basic Config

import type { Field } from 'payload'

export const MySelectField: Field = {
  name: 'status',
  type: 'select',
  options: [
    { label: 'Draft',     value: 'draft' },
    { label: 'Published', value: 'published' },
    { label: 'Archived',  value: 'archived' },
  ],
}

Config Options

Option Required Description
name DB property name
options Array of strings or { label, value } objects
hasMany true → allows multiple selections (stored as array)
filterOptions Dynamically filter visible/saveable options
enumName Custom Postgres enum name (auto-generated if omitted)
dbName Custom join table name when hasMany: true (Postgres)
unique DB-level unique constraint
index Add index for faster queries
localized Per-locale values
saveToJWT Include value in auth JWT
defaultValue Default option value
required Require a selection
hidden Exclude from all APIs (still stored in DB)
virtual Disable DB storage, or link to relationship
interfaceName Reusable TS interface + GraphQL type
typescriptSchema Override TS type generation with JSON schema

GraphQL constraint: option values must not contain hyphens or special characters — only underscores allowed. Values with special characters are reformatted automatically for GraphQL enums.

hasMany — Multi-Select

{
  name: 'selectedFeatures',
  type: 'select',
  hasMany: true,
  admin: {
    isClearable: true,
    isSortable: true,  // drag-and-drop reordering
  },
  options: [
    { label: 'Metallic Paint',         value: 'metallic_paint' },
    { label: 'Alloy Wheels',           value: 'alloy_wheels' },
    { label: 'Carbon Fiber Dashboard', value: 'carbon_fiber_dashboard' },
  ],
}
  • hasMany: true stores an array of values
  • isSortable only works when hasMany: true
  • Postgres creates a separate join table (dbName to override its name)

filterOptions

Dynamically filters which options appear in the Admin UI and which can be saved:

{
  type: 'select',
  options: [
    { label: 'One',   value: 'one' },
    { label: 'Two',   value: 'two' },
    { label: 'Three', value: 'three' },
  ],
  filterOptions: ({ options, data }) =>
    data.disallowOption1
      ? options.filter(o => (typeof o === 'string' ? o : o.value) !== 'one')
      : options,
}

Use cases:

  • Admin-only options based on req.user.role
  • Dependent dropdowns (city filtered by selected state)

Unlike filterOptions on wiki/payloadcms/fields-relationship / wiki/payloadcms/fields-overview fields, the return value here is an array of options, not a query constraint.

Admin Options

Property Description
isClearable Show a clear/reset button in the UI
isSortable Enable drag-and-drop reordering (requires hasMany: true)
placeholder Custom placeholder text or function

Custom Components

Server Component (Field)

import type { SelectFieldServerComponent } from 'payload'
import { SelectField } from '@payloadcms/ui'

export const CustomSelectFieldServer: SelectFieldServerComponent = ({
  clientField, path, schemaPath, permissions,
}) => (
  <SelectField field={clientField} path={path} schemaPath={schemaPath} permissions={permissions} />
)

Client Component (Field)

'use client'
import type { SelectFieldClientComponent } from 'payload'
import { SelectField } from '@payloadcms/ui'

export const CustomSelectFieldClient: SelectFieldClientComponent = (props) => (
  <SelectField {...props} />
)

Label Components

Use FieldLabel from @payloadcms/ui for both server and client label overrides — pass label, path, and required from clientField/field.

Key Takeaways

  • options values must use underscores, not hyphens (GraphQL enum constraint)
  • hasMany: true switches storage to an array; Postgres creates a join table
  • filterOptions controls both UI display and what values can be saved — useful for role-based or dependent dropdowns
  • enumName / dbName let you control Postgres schema naming explicitly
  • isSortable drag-and-drop only activates when hasMany: true
  • Use interfaceName to generate a reusable TypeScript interface and GraphQL type for this field's enum

Sources