Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

Fields Overview

Fields are the building blocks of Payload. They define the schema of the Documents that will be stored in the Database, as well as automatically generate the corresponding UI within the Admin Panel.

There are many Field Types to choose from, ranging anywhere from simple text strings to nested arrays and blocks. Most fields save data to the database, while others are strictly presentational. Fields can have Custom Validations, Conditional Logic, Access Control, Hooks, and so much more.

Fields can be endlessly customized in their appearance and behavior without affecting their underlying data structure. Fields are designed to withstand heavy modification or even complete replacement through the use of Custom Field Components.

To configure fields, use the fields property in your Collection or Global config:

1
import type { CollectionConfig } from 'payload'
2
3
export const Page: CollectionConfig = {
4
// ...
5
fields: [
6
// ...
7
]
8
}

Field Types

Payload provides a wide variety of built-in Field Types, each with its own unique properties and behaviors that determine which values it can accept, how it is presented in the API, and how it will be rendered in the Admin Panel.

To configure fields, use the fields property in your Collection or Global config:

1
import type { CollectionConfig } from 'payload'
2
3
export const Page: CollectionConfig = {
4
slug: 'pages',
5
fields: [
6
{
7
name: 'field',
8
type: 'text',
9
}
10
]
11
}

There are three main categories of fields in Payload:

To begin writing fields, first determine which Field Type best supports your application. Then to author your field accordingly using the Field Options for your chosen field type.

Data Fields

Data Fields are used to store data in the Database. All Data Fields have a name property. This is the key that will be used to store the field's value.

Here are the available Data Fields:

  • Array - for repeating content, supports nested fields
  • Blocks - for block-based content, supports nested fields
  • Checkbox - saves boolean true / false values
  • Code - renders a code editor interface that saves a string
  • Date - renders a date picker and saves a timestamp
  • Email - ensures the value is a properly formatted email address
  • Group - nests fields within a keyed object
  • JSON - renders a JSON editor interface that saves a JSON object
  • Number - saves numeric values
  • Point - for location data, saves geometric coordinates
  • Radio - renders a radio button group that allows only one value to be selected
  • Relationship - assign relationships to other collections
  • Rich Text - renders a fully extensible rich text editor
  • Select - renders a dropdown / picklist style value selector
  • Tabs (Named) - similar to group, but renders nested fields within a tabbed layout
  • Text - simple text input that saves a string
  • Textarea - similar to text, but allows for multi-line input
  • Upload - allows local file and image upload

Presentational Fields

Presentational Fields do not store data in the database. Instead, they are used to organize and present other fields in the Admin Panel, or to add custom UI components.

Here are the available Presentational Fields:

  • Collapsible - nests fields within a collapsible component
  • Row - aligns fields horizontally
  • Tabs (Unnamed) - nests fields within a tabbed layout
  • UI - blank field for custom UI components

Virtual Fields

Virtual fields are used to display data that is not stored in the database. They are useful for displaying computed values that populate within the APi response through hooks, etc.

Here are the available Virtual Fields:

  • Join - achieves two-way data binding between fields

Field Options

All fields require at least the type property. This matches the field to its corresponding Field Type to determine its appearance and behavior within the Admin Panel. Each Field Type has its own unique set of options based on its own type.

To set a field's type, use the type property in your Field Config:

1
import type { Field } from 'payload'
2
3
export const MyField: Field = {
4
type: 'text',
5
name: 'myField',
6
}

Field Names

All Data Fields require a name property. This is the key that will be used to store and retrieve the field's value in the database. This property must be unique amongst this field's siblings.

To set a field's name, use the name property in your Field Config:

1
import type { Field } from 'payload'
2
3
export const MyField: Field = {
4
type: 'text',
5
name: 'myField',
6
}

Payload reserves various field names for internal use. Using reserved field names will result in your field being sanitized from the config.

The following field names are forbidden and cannot be used:

  • __v
  • salt
  • hash
  • file

Field-level Hooks

In addition to being able to define Hooks on a document-level, you can define extremely granular logic field-by-field.

To define Field-level Hooks, use the hooks property in your Field Config:

1
import type { Field } from 'payload'
2
3
export const MyField: Field = {
4
type: 'text',
5
name: 'myField',
6
hooks: {
7
// ...
8
}
9
}

For full details on Field-level Hooks, see the Field Hooks documentation.

Field-level Access Control

In addition to being able to define Access Control on a document-level, you can define extremely granular permissions field-by-field.

To define Field-level Access Control, use the access property in your Field Config:

1
import type { Field } from 'payload'
2
3
export const MyField: Field = {
4
type: 'text',
5
name: 'myField',
6
access: {
7
// ...
8
}
9
}

For full details on Field-level Access Control, see the Field Access Control documentation.

Default Values

Fields can be optionally prefilled with initial values. This is used in both the Admin Panel as well as API requests to populate missing or undefined field values during the create or update operations.

To set a field's default value, use the defaultValue property in your Field Config:

1
import type { Field } from 'payload'
2
3
export const MyField: Field = {
4
type: 'text',
5
name: 'myField',
6
defaultValue: 'Hello, World!',
7
}

Default values can be defined as a static value or a function that returns a value. When a defaultValue is defined statically, Payload's Database Adapters will apply it to the database schema or models.

Functions can be written to make use of the following argument properties:

  • user - the authenticated user object
  • locale - the currently selected locale string
  • req - the PayloadRequest object

Here is an example of a defaultValue function:

1
import type { Field } from 'payload'
2
3
const translation: {
4
en: 'Written by'
5
es: 'Escrito por'
6
}
7
8
export const myField: Field = {
9
name: 'attribution',
10
type: 'text',
11
defaultValue: ({ user, locale, req }) =>
12
`${translation[locale]} ${user.name}`,
13
}

Validation

Fields are automatically validated based on their Field Type and other Field Options such as required or min and max value constraints. If needed, however, field validations can be customized or entirely replaced by providing your own custom validation functions.

To set a custom field validation function, use the validate property in your Field Config:

1
import type { Field } from 'payload'
2
3
export const MyField: Field = {
4
type: 'text',
5
name: 'myField',
6
validate: value => Boolean(value) || 'This field is required'
7
}

Custom validation functions should return either true or a string representing the error message to display in API responses.

The following arguments are provided to the validate function:

Argument

Description

value

The value of the field being validated.

ctx

An object with additional data and context. More details

Validation Context

The ctx argument contains full document data, sibling field data, the current operation, and other useful information such as currently authenticated user:

1
import type { Field } from 'payload'
2
3
export const MyField: Field = {
4
type: 'text',
5
name: 'myField',
6
validate: (val, { user }) =>
7
Boolean(user) || 'You must be logged in to save this field',
8
}

The following additional properties are provided in the ctx object:

Property

Description

data

An object containing the full collection or global document currently being edited.

siblingData

An object containing document data that is scoped to only fields within the same parent of this field.

operation

Will be create or update depending on the UI action or API call.

id

The id of the current document being edited. id is undefined during the create operation.

req

The current HTTP request object. Contains payload, user, etc.

Reusing Default Field Validations

When using custom validation functions, Payload will use yours in place of the default. However, you might want to simply augment the default validation with your own custom logic.

To reuse default field validations, call them from within your custom validation function:

1
import { text } from 'payload/shared'
2
3
const field: Field = {
4
name: 'notBad',
5
type: 'text',
6
validate: (val, args) => {
7
if (val === 'bad') return 'This cannot be "bad"'
8
return text(val, args)
9
},
10
}

Async Field Validations

Custom validation functions can also be asynchronous depending on your needs. This makes it possible to make requests to external services or perform other miscellaneous asynchronous logic.

To write asynchronous validation functions, use the async keyword to define your function:

1
import type { CollectionConfig } from 'payload'
2
3
export const Orders: CollectionConfig = {
4
slug: 'orders',
5
fields: [
6
{
7
name: 'customerNumber',
8
type: 'text',
9
validate: async (val, { operation }) => {
10
if (operation !== 'create') return true
11
const response = await fetch(`https://your-api.com/customers/${val}`)
12
if (response.ok) return true
13
return 'The customer number provided does not match any customers within our records.'
14
},
15
},
16
],
17
}

Custom ID Fields

All Collections automatically generate their own ID field. If needed, you can override this behavior by providing an explicit ID field to your config. This field should either be required or have a hook to generate the ID dynamically.

To define a custom ID field, add a top-level field with the name property set to id:

1
import type { CollectionConfig } from 'payload'
2
3
export const MyCollection: CollectionConfig = {
4
// ...
5
fields: [
6
{
7
name: 'id',
8
required: true,
9
type: 'number',
10
},
11
],
12
}

Admin Options

You can customize the appearance and behavior of fields within the Admin Panel through the admin property of any Field Config:

1
import type { CollectionConfig } from 'payload'
2
3
export const CollectionConfig: CollectionConfig = {
4
// ...
5
fields: [
6
// ...
7
{
8
name: 'myField',
9
type: 'text',
10
admin: {
11
// ...
12
},
13
}
14
]
15
}

The following options are available:

Option

Description

condition

Programmatically show / hide fields based on other fields. More details.

components

All Field Components can be swapped out for Custom Components that you define.

description

Helper text to display alongside the field to provide more information for the editor. More details.

position

Specify if the field should be rendered in the sidebar by defining position: 'sidebar'.

width

Restrict the width of a field. You can pass any string-based value here, be it pixels, percentages, etc. This property is especially useful when fields are nested within a Row type where they can be organized horizontally.

style

CSS Properties to inject into the root element of the field.

className

Attach a CSS class attribute to the root DOM element of a field.

readOnly

Setting a field to readOnly has no effect on the API whatsoever but disables the admin component's editability to prevent editors from modifying the field's value.

disabled

If a field is disabled, it is completely omitted from the Admin Panel entirely.

disableBulkEdit

Set disableBulkEdit to true to prevent fields from appearing in the select options when making edits for multiple documents. Defaults to true for UI fields.

disableListColumn

Set disableListColumn to true to prevent fields from appearing in the list view column selector.

disableListFilter

Set disableListFilter to true to prevent fields from appearing in the list view filter options.

hidden

Will transform the field into a hidden input type. Its value will still submit with requests in the Admin Panel, but the field itself will not be visible to editors.

Field Descriptions

Field Descriptions are used to provide additional information to the editor about a field, such as special instructions. Their placement varies from field to field, but typically are displayed with subtle style differences beneath the field inputs.

A description can be configured in three ways:

To add a Custom Description to a field, use the admin.description property in your Field Config:

1
import type { SanitizedCollectionConfig } from 'payload'
2
3
export const MyCollectionConfig: SanitizedCollectionConfig = {
4
// ...
5
fields: [
6
// ...
7
{
8
name: 'myField',
9
type: 'text',
10
admin: {
11
description: 'Hello, world!'
12
},
13
},
14
]
15
}

Description Functions

Custom Descriptions can also be defined as a function. Description Functions are executed on the server and can be used to format simple descriptions based on the user's current Locale.

To add a Description Function to a field, set the admin.description property to a function in your Field Config:

1
import type { SanitizedCollectionConfig } from 'payload'
2
3
export const MyCollectionConfig: SanitizedCollectionConfig = {
4
// ...
5
fields: [
6
// ...
7
{
8
name: 'myField',
9
type: 'text',
10
admin: {
11
description: ({ t }) => `${t('Hello, world!')}`
12
},
13
},
14
]
15
}

All Description Functions receive the following arguments:

Argument

Description

t

The t function used to internationalize the Admin Panel. More details

Conditional Logic

You can show and hide fields based on what other fields are doing by utilizing conditional logic on a field by field basis. The condition property on a field's admin config accepts a function which takes three arguments:

  • data - the entire document's data that is currently being edited
  • siblingData - only the fields that are direct siblings to the field with the condition
  • { user } - the final argument is an object containing the currently authenticated user

The condition function should return a boolean that will control if the field should be displayed or not.

Example:

1
{
2
fields: [
3
{
4
name: 'enableGreeting',
5
type: 'checkbox',
6
defaultValue: false,
7
},
8
{
9
name: 'greeting',
10
type: 'text',
11
admin: {
12
condition: (data, siblingData, { user }) => {
13
if (data.enableGreeting) {
14
return true
15
} else {
16
return false
17
}
18
},
19
},
20
},
21
]
22
}

Custom Components

Within the Admin Panel, fields are represented in three distinct places:

  • Field - The actual form field rendered in the Edit View.
  • Cell - The table cell component rendered in the List View.
  • Filter - The filter component rendered in the List View.

To swap in Field Components with your own, use the admin.components property in your Field Config:

1
import type { CollectionConfig } from 'payload'
2
3
export const CollectionConfig: CollectionConfig = {
4
// ...
5
fields: [
6
// ...
7
{
8
// ...
9
admin: {
10
components: {
11
// ...
12
},
13
},
14
}
15
]
16
}

The following options are available:

Component

Description

Field

The form field rendered of the Edit View. More details.

Cell

The table cell rendered of the List View. More details.

Filter

The filter component rendered in the List View. More details.

Label

Override the default Label of the Field Component. More details.

Error

Override the default Error of the Field Component. More details.

Description

Override the default Description of the Field Component. More details.

beforeInput

An array of elements that will be added before the input of the Field Component. More details.

afterInput

An array of elements that will be added after the input of the Field Component. More details.

Field

The Field Component is the actual form field rendered in the Edit View. This is the input that user's will interact with when editing a document.

To swap in your own Field Component, use the admin.components.Field property in your Field Config:

1
import type { CollectionConfig } from 'payload'
2
3
export const CollectionConfig: CollectionConfig = {
4
// ...
5
fields: [
6
// ...
7
{
8
// ...
9
admin: {
10
components: {
11
Field: '/path/to/MyFieldComponent',
12
},
13
},
14
}
15
]
16
}

For details on how to build Custom Components, see Building Custom Components.

Default Props

All Field Components receive the following props by default:

Property

Description

docPreferences

An object that contains the Preferences for the document.

field

In Client Components, this is the sanitized Client Field Config. In Server Components, this is the original Field Config. Server Components will also receive the sanitized field config through theclientField prop (see below).

locale

The locale of the field. More details.

readOnly

A boolean value that represents if the field is read-only or not.

user

The currently authenticated user. More details.

validate

A function that can be used to validate the field.

path

A string representing the direct, dynamic path to the field at runtime, i.e. myGroup.myArray.0.myField.

schemaPath

A string representing the direct, static path to the Field Config, i.e. posts.myGroup.myArray.myField.

indexPath

A hyphen-notated string representing the path to the field within the nearest named ancestor field, i.e. 0-0

In addition to the above props, all Server Components will also receive the following props:

Property

Description

clientField

The serializable Client Field Config.

field

The Field Config.

data

The current document being edited.

i18n

The i18n object.

payload

The Payload class.

permissions

The field permissions based on the currently authenticated user.

siblingData

The data of the field's siblings.

user

The currently authenticated user. More details.

value

The value of the field at render-time.

Sending and receiving values from the form

When swapping out the Field component, you are responsible for sending and receiving the field's value from the form itself.

To do so, import the useField hook from @payloadcms/ui and use it to manage the field's value:

1
'use client'
2
import { useField } from '@payloadcms/ui'
3
4
export const CustomTextField: React.FC = () => {
5
const { value, setValue } = useField()
6
7
return (
8
<input
9
onChange={(e) => setValue(e.target.value)}
10
value={value}
11
/>
12
)
13
}
TypeScript

When building Custom Field Components, you can import the client field props to ensure type safety in your component. There is an explicit type for the Field Component, one for every Field Type and server/client environment. The convention is to prepend the field type onto the target type, i.e. TextFieldClientComponent:

1
import type {
2
TextFieldClientComponent,
3
TextFieldServerComponent,
4
TextFieldClientProps,
5
TextFieldServerProps,
6
// ...and so on for each Field Type
7
} from 'payload'

See each individual Field Type for exact type imports.

Cell

The Cell Component is rendered in the table of the List View. It represents the value of the field when displayed in a table cell.

To swap in your own Cell Component, use the admin.components.Cell property in your Field Config:

1
import type { Field } from 'payload'
2
3
export const myField: Field = {
4
name: 'myField',
5
type: 'text',
6
admin: {
7
components: {
8
Cell: '/path/to/MyCustomCellComponent',
9
},
10
},
11
}

All Cell Components receive the same Default Field Component Props, plus the following:

Property

Description

link

A boolean representing whether this cell should be wrapped in a link.

onClick

A function that is called when the cell is clicked.

For details on how to build Custom Components themselves, see Building Custom Components.

Filter

The Filter Component is the actual input element rendered within the "Filter By" dropdown of the List View used to represent this field when building filters.

To swap in your own Filter Component, use the admin.components.Filter property in your Field Config:

1
import type { Field } from 'payload'
2
3
export const myField: Field = {
4
name: 'myField',
5
type: 'text',
6
admin: {
7
components: {
8
Filter: '/path/to/MyCustomFilterComponent',
9
},
10
},
11
}

All Custom Filter Components receive the same Default Field Component Props.

For details on how to build Custom Components themselves, see Building Custom Components.

Label

The Label Component is rendered anywhere a field needs to be represented by a label. This is typically used in the Edit View, but can also be used in the List View and elsewhere.

To swap in your own Label Component, use the admin.components.Label property in your Field Config:

1
import type { Field } from 'payload'
2
3
export const myField: Field = {
4
name: 'myField',
5
type: 'text',
6
admin: {
7
components: {
8
Label: '/path/to/MyCustomLabelComponent',
9
},
10
},
11
}

All Custom Label Components receive the same Default Field Component Props.

For details on how to build Custom Components themselves, see Building Custom Components.

TypeScript

When building Custom Label Components, you can import the component types to ensure type safety in your component. There is an explicit type for the Label Component, one for every Field Type and server/client environment. The convention is to append LabelServerComponent or LabelClientComponent to the type of field, i.e. TextFieldLabelClientComponent.

1
import type {
2
TextFieldLabelServerComponent,
3
TextFieldLabelClientComponent,
4
// ...and so on for each Field Type
5
} from 'payload'

Description

Alternatively to the Description Property, you can also use a Custom Component as the Field Description. This can be useful when you need to provide more complex feedback to the user, such as rendering dynamic field values or other interactive elements.

To add a Description Component to a field, use the admin.components.Description property in your Field Config:

1
import type { SanitizedCollectionConfig } from 'payload'
2
3
export const MyCollectionConfig: SanitizedCollectionConfig = {
4
// ...
5
fields: [
6
// ...
7
{
8
name: 'myField',
9
type: 'text',
10
admin: {
11
components: {
12
Description: '/path/to/MyCustomDescriptionComponent',
13
}
14
}
15
}
16
]
17
}

All Custom Description Components receive the same Default Field Component Props.

For details on how to build a Custom Components themselves, see Building Custom Components.

TypeScript

When building Custom Description Components, you can import the component props to ensure type safety in your component. There is an explicit type for the Description Component, one for every Field Type and server/client environment. The convention is to append DescriptionServerComponent or DescriptionClientComponent to the type of field, i.e. TextFieldDescriptionClientComponent.

1
import type {
2
TextFieldDescriptionServerComponent,
3
TextFieldDescriptionClientComponent,
4
// And so on for each Field Type
5
} from 'payload'

Error

The Error Component is rendered when a field fails validation. It is typically displayed beneath the field input in a visually-compelling style.

To swap in your own Error Component, use the admin.components.Error property in your Field Config:

1
import type { Field } from 'payload'
2
3
export const myField: Field = {
4
name: 'myField',
5
type: 'text',
6
admin: {
7
components: {
8
Error: '/path/to/MyCustomErrorComponent',
9
},
10
},
11
}

All Error Components receive the Default Field Component Props.

For details on how to build Custom Components themselves, see Building Custom Components.

TypeScript

When building Custom Error Components, you can import the component types to ensure type safety in your component. There is an explicit type for the Error Component, one for every Field Type and server/client environment. The convention is to append ErrorServerComponent or ErrorClientComponent to the type of field, i.e. TextFieldErrorClientComponent.

1
import type {
2
TextFieldErrorServerComponent,
3
TextFieldErrorClientComponent,
4
// And so on for each Field Type
5
} from 'payload'

afterInput and beforeInput

With these properties you can add multiple components before and after the input element, as their name suggests. This is useful when you need to render additional elements alongside the field without replacing the entire field component.

To add components before and after the input element, use the admin.components.beforeInput and admin.components.afterInput properties in your Field Config:

1
import type { SanitizedCollectionConfig } from 'payload'
2
3
export const MyCollectionConfig: SanitizedCollectionConfig = {
4
// ...
5
fields: [
6
// ...
7
{
8
name: 'myField',
9
type: 'text',
10
admin: {
11
components: {
12
beforeInput: ['/path/to/MyCustomComponent'],
13
afterInput: ['/path/to/MyOtherCustomComponent'],
14
}
15
}
16
}
17
]
18
}

All afterInput and beforeInput Components receive the same Default Field Component Props.

For details on how to build Custom Components, see Building Custom Components.

TypeScript

You can import the Payload Field type as well as other common types from the payload package. More details.

1
import type { Field } from 'payload'
Next

Array Field