obsidian/wiki/payloadcms/fields-basic.md
2026-05-15 15:13:56 +01:00

11 KiB

tags topic sources created
payloadcms
tech-patterns
payloadcms
https://payloadcms.com/docs/fields/overview
https://payloadcms.com/docs/fields/text
https://payloadcms.com/docs/fields/textarea
https://payloadcms.com/docs/fields/number
https://payloadcms.com/docs/fields/email
https://payloadcms.com/docs/fields/date
https://payloadcms.com/docs/fields/checkbox
https://payloadcms.com/docs/fields/code
https://payloadcms.com/docs/fields/json
https://payloadcms.com/docs/fields/point
https://payloadcms.com/docs/fields/radio
https://payloadcms.com/docs/fields/select
https://payloadcms.com/docs/fields/ui
2026-05-15

PayloadCMS — Fields: Basic

Overview

Scalar (basic) fields store a single value per document. They map directly to database columns and drive typed inputs in the Admin Panel. All fields live inside the fields array of a wiki/payloadcms/configuration (Collection or Global).

See wiki/payloadcms/fields-complex for structural/relational fields.

Field Types Quick Reference

Field Type string Key options
Text text minLength, maxLength, hasMany, unique
Textarea textarea minLength, maxLength, admin.rows
Number number min, max, hasMany, admin.step
Email email unique, index
Date date timezone, admin.date.pickerAppearance
Checkbox checkbox defaultValue (boolean)
Code code admin.language, admin.editorOptions
JSON json jsonSchema (local or remote)
Point point index defaults to 2dsphere, not supported in SQLite
Radio radio options (required), admin.layout
Select select options, hasMany, filterOptions, enumName
UI ui admin.components.Field (required), presentational only

Common Field Options

These options are shared by almost all data-storing fields:

Option Type Description
name * string Property name in DB and API. Required for data fields.
label string | Record<string,string> Admin Panel label, auto-generated from name if omitted.
required boolean Prevents saving without a value.
defaultValue any Initial value; can be a static value or async function.
unique boolean DB-level unique index across the collection.
index boolean Creates a DB index for faster queries.
localized boolean Stores a per-locale copy. Requires localization enabled globally.
hidden boolean Hides from all APIs and Admin; still saved to DB.
validate function Custom validation, runs on both client and server.
hooks object beforeValidate, beforeChange, afterChange, afterRead.
access object Field-level read/create/update access control functions.
saveToJWT boolean Include value in user JWT (auth collections only, top-level fields).
virtual boolean | string true = not persisted to DB; string path = virtual relationship link.
custom object Arbitrary extension data for plugins.
typescriptSchema JSONSchema Override generated TypeScript type with a JSON schema.

Admin-level sub-options available on all fields (via admin: {}):

Option Description
description Help text rendered below the field.
condition (data, siblingData) => boolean — conditional rendering.
readOnly Renders as read-only in Admin.
disabled Disables the field UI (granular: { field?, column?, filter?, ... }).
position 'sidebar' to move field to the document sidebar.
width CSS width for use inside row fields (e.g. '50%').
components Override Field, Label, Cell React components.

Each Field

Text

Stores a string. Most commonly used field.

import type { Field } from 'payload'

const titleField: Field = {
  name: 'pageTitle',
  type: 'text',
  required: true,
  minLength: 3,
  maxLength: 120,
  admin: {
    placeholder: 'Enter page title...',
    autoComplete: 'off',
    rtl: false,
  },
}

Extra options: minLength, maxLength, hasMany (array of strings), minRows, maxRows (when hasMany), admin.placeholder, admin.autoComplete, admin.rtl.

Slug Field shortcut: import { slugField } from 'payload' — auto-generates URL slug from another field with a lock/unlock UI.

Gotcha: unique: true creates a collection-wide DB index, not per-document uniqueness.


Textarea

Nearly identical to Text but renders a taller input — use for descriptions, bios, meta.

const descField: Field = {
  name: 'metaDescription',
  type: 'textarea',
  maxLength: 160,
  admin: {
    rows: 3,
    placeholder: 'Short summary...',
  },
}

Extra options: same as Text plus admin.rows (default 2).


Number

Stores a numeric value.

const priceField: Field = {
  name: 'price',
  type: 'number',
  min: 0,
  required: true,
  admin: {
    step: 0.01,
    placeholder: '0.00',
  },
}

Extra options: min, max, hasMany, minRows, maxRows, admin.step, admin.placeholder, admin.autoComplete.


Email

Like Text but validates that the value is a valid email address.

const emailField: Field = {
  name: 'contactEmail',
  type: 'email',
  required: true,
  unique: true,
  admin: {
    placeholder: 'user@example.com',
  },
}

No unique-to-email options beyond standard text options. Format validation is automatic.


Date

Stores a full ISO datetime string (YYYY-MM-DDTHH:mm:ss.SSSZ). UI uses react-datepicker.

const publishedAtField: Field = {
  name: 'publishedAt',
  type: 'date',
  required: true,
  admin: {
    date: {
      pickerAppearance: 'dayAndTime',   // dayAndTime | dayOnly | timeOnly | monthOnly
      displayFormat: 'd MMM yyyy HH:mm',
      timeIntervals: 15,
    },
  },
}

Timezone support:

{
  name: 'eventTime',
  type: 'date',
  timezone: {
    defaultTimezone: 'America/New_York',
    supportedTimezones: [
      { label: 'New York', value: 'America/New_York' },
      { label: 'London',   value: 'Europe/London' },
    ],
  },
}

Timezone value is saved in a companion column <fieldName>_tz. Date is always stored in UTC — handle conversion in your frontend.

displayFormat only affects the cell display; the stored value is always full ISO.


Checkbox

Stores a boolean.

const featuredField: Field = {
  name: 'isFeatured',
  type: 'checkbox',
  defaultValue: false,
}

Gotcha: When required: true, defaultValue must be true — otherwise required validation will always fail on false.


Code

Stores a string but renders a Monaco-editor code block in Admin.

const snippetField: Field = {
  name: 'trackingCode',
  type: 'code',
  admin: {
    language: 'javascript',  // any Monaco language slug
    editorOptions: { lineNumbers: 'off' },
  },
}

Gotcha: Saves as raw string to DB — not parsed. Different from JSON field.


JSON

Stores raw JSON (parsed object/array) in the DB. Also Monaco-editor UI.

const configField: Field = {
  name: 'settings',
  type: 'json',
  jsonSchema: {
    uri: 'a://schema/settings.json',       // required — must be unique URI
    fileMatch: ['a://schema/settings.json'], // required
    schema: {
      type: 'object',
      properties: {
        theme: { enum: ['light', 'dark'] },
      },
    },
  },
}

jsonSchema enables typeahead in Admin and validates on save. Can also point to a remote URL — Payload fetches the schema.

Gotcha: Code field stores string; JSON field stores a parsed value — do not confuse them.


Point

Stores GeoJSON [longitude, latitude] coordinates with an automatic 2dsphere index.

const locationField: Field = {
  name: 'location',
  type: 'point',
}

Supports geospatial query operators: near, within (polygon), intersects (polygon).

Gotcha: Not supported in SQLite. Disabling the index (index: false) removes geospatial query support.


Radio

Single-select from a predefined list. Renders a radio group.

const statusField: Field = {
  name: 'status',
  type: 'radio',
  options: [
    { label: 'Draft',     value: 'draft' },
    { label: 'Published', value: 'published' },
    { label: 'Archived',  value: 'archived' },
  ],
  defaultValue: 'draft',
  admin: {
    layout: 'horizontal',  // horizontal | vertical
  },
}

Gotcha: Option value strings must not contain hyphens — GraphQL enum constraint. Underscores are fine.


Select

Dropdown single or multi-select from a predefined list.

const tagsField: Field = {
  name: 'tags',
  type: 'select',
  hasMany: true,
  options: [
    { label: 'News',     value: 'news' },
    { label: 'Tutorial', value: 'tutorial' },
    { label: 'Release',  value: 'release' },
  ],
  admin: {
    isClearable: true,
    isSortable: true,   // drag-and-drop reorder, only when hasMany
  },
}

filterOptions — function receiving { options, data, siblingData, ... } that returns a filtered options array (different from relationship filterOptions which returns a Where query).

Extra options: enumName (custom Postgres enum name), dbName (custom join table name when hasMany), interfaceName.


UI

Presentational-only. No data stored. Renders a custom React component anywhere in the field schema.

const helpTextField: Field = {
  name: 'myHelper',
  type: 'ui',
  admin: {
    components: {
      Field: '/path/to/MyHelpText',   // required
      Cell: '/path/to/MyHelpCell',    // optional — list view column
    },
  },
}

Use cases: custom buttons (Refund, Clear Cache, View Page), contextual help text, action components.

Gotcha: admin.components.Field is required — without it nothing renders. Does not participate in validation or hooks.


Gotchas

  • unique: true on nested fields (inside Array/Group) creates a collection-wide index, not per-row uniqueness. Use a custom validate for per-row enforcement.
  • hidden: true still persists data to DB — use field access to truly restrict reads.
  • localized: true requires global localization config (i18n) to be enabled first.
  • virtual: true prevents DB storage entirely; useful for computed/derived fields.
  • Radio/Select values must not contain hyphens — GraphQL enum naming constraint.
  • Point field is unsupported in SQLite databases.
  • Date timezone column is auto-named <fieldName>_tz; date itself stored in UTC.