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.

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 two 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
  • Join - achieves two-way data binding between fields
  • Row - aligns fields horizontally
  • Tabs (Unnamed) - nests fields within a tabbed layout
  • UI - blank field for custom UI components

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

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 }) =>
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:

ArgumentDescription
valueThe value of the field being validated.
ctxAn 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:

PropertyDescription
dataAn object containing the full collection or global document currently being edited.
siblingDataAn object containing document data that is scoped to only fields within the same parent of this field.
operationWill be create or update depending on the UI action or API call.
idThe id of the current document being edited. id is undefined during the create operation.
reqThe 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
}

Admin Options

In addition to each field's base configuration, you can use the admin key to specify traits and properties for fields that will only effect how they are rendered within the Admin Panel, such as their appearance or behavior.

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

For full details on Admin Options, see the Field Admin Options documentation.

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
}

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