--- tags: [payloadcms, tech-patterns] topic: payloadcms sources: - 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 created: 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|Configuration]] (Collection or Global). See [[wiki/payloadcms/fields-complex|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` | 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. ```ts 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. ```ts 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. ```ts 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. ```ts 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`. ```ts 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:** ```ts { 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 `_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`. ```ts 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. ```ts 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. ```ts 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. ```ts 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. ```ts 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. ```ts 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. ```ts 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 `_tz`; date itself stored in UTC. ## Related - [[wiki/payloadcms/fields-complex|Fields: Complex]] - [[wiki/payloadcms/configuration|Configuration]]