Fields Overview

Fields are defined as an array on Collections and Globals via the fields key. They define the shape of the data that will be stored as well as automatically construct the corresponding Admin UI.

The required type property on a field determines what values it can accept, how it is presented in the API, and how the field will be rendered in the admin interface.

Simple collection with two fields:

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

Field types

  • Array - for repeating content, supports nested fields
  • Blocks - block-based fields, allowing powerful layout creation
  • Checkbox - boolean true / false checkbox
  • Code - code editor that saves a string to the database
  • Collapsible - used for admin layout, nest fields within a collapsible component
  • Date - date / time field that saves a timestamp
  • Email - validates the entry is a properly formatted email
  • Group - nest fields within an object
  • JSON - saves actual JSON in the database
  • Number - field that enforces that its value be a number
  • Point - geometric coordinates for location data
  • Radio - radio button group, allowing only one value to be selected
  • Relationship - assign relationships to other collections
  • Rich Text - fully extensible Rich Text editor
  • Row - used for admin field layout, no effect on data shape
  • Select - dropdown / picklist style value selector
  • Tabs - used for admin layout, nest fields within tabs
  • Text - simple text input
  • Textarea - allows a bit larger of a text editor
  • Upload - allows local file and image upload
  • UI - inject your own custom components and do whatever you need

Field-level hooks

One of the most powerful parts about Payload is its ability for you to define field-level hooks that can control the logic of your fields to a fine-grained level. for more information about how to define field hooks, click here.

Field-level access control

In addition to being able to define access control on a document-level, you can define extremely granular permissions on a field by field level. For more information about field-level access control, click here.

Field names

All 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 within the Collection, Global, or nested group that it is defined in.

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

Validation

Field validation is enforced automatically based on the field type and other properties such as required or min and max value constraints on certain field types. This default behavior can be replaced by providing your own validate function for any field. It will be used on both the frontend and the backend, so it should not rely on any Node-specific packages. The validation function can be either synchronous or asynchronous and expects to return either true or a string error message to display in both API responses and within the Admin panel.

There are two arguments available to custom validation functions.

  1. The value which is currently assigned to the field
  2. An optional object with dynamic properties for more complex validation having the following:
PropertyDescription
dataAn object of the full collection or global document.
siblingDataAn object of the document data limited to fields within the same parent to the field.
operationWill be "create" or "update" depending on the UI action or API call.
idThe value of the collection id, will be undefined on create request.
tThe function for translating text, more.
userThe currently authenticated user object.
payloadIf the validate function is being executed on the server, Payload will be exposed for easily running local operations.

Example:

1
import { CollectionConfig } from 'payload/types'
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') {
11
// skip validation on update
12
return true
13
}
14
const response = await fetch(`https://your-api.com/customers/${val}`)
15
if (response.ok) {
16
return true
17
}
18
19
return 'The customer number provided does not match any customers within our records.'
20
},
21
},
22
],
23
}

When supplying a field validate function, Payload will use yours in place of the default. To make use of the default field validation in your custom logic you can import, call and return the result as needed.

For example:

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

Customizable ID

Collections ID fields are generated automatically by default. An explicit id field can be declared in the fields array to override this behavior. Users are then required to provide a custom ID value when creating a record through the Admin UI or API. Valid ID types are number and text. When using the text value, remember that it shouldn't contain the / (slash) sign, as the API will read it separately and this can result in unexpected behavior.

Example:

1
{
2
fields: [
3
{
4
name: 'id',
5
type: 'number',
6
},
7
],
8
}

Admin config

In addition to each field's base configuration, you can define specific traits and properties for fields that only have effect on how they are rendered in the Admin panel. The following properties are available for all fields within the admin property:

OptionDescription
conditionYou can programmatically show / hide fields based on what other fields are doing. Click here for more info.
componentsAll field components can be completely and easily swapped out for custom components that you define. Click here for more info.
descriptionHelper text to display with the field to provide more information for the editor user. Click here for more info.
positionSpecify if the field should be rendered in the sidebar by defining position: 'sidebar'.
widthRestrict 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.
styleAttach raw CSS style properties to the root DOM element of a field.
classNameAttach a CSS class name to the root DOM element of a field.
readOnlySetting 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.
disabledIf a field is disabled, it is completely omitted from the Admin panel.
disableBulkEditSet disableBulkEdit to true to prevent fields from appearing in the select options when making edits for multiple documents.
disableListColumnSet disableListColumn to true to prevent fields from appearing in the list view column selector.
disableListFilterSet disableListFilter to true to prevent fields from appearing in the list view filter options.
hiddenSetting a field's hidden property on its admin config will transform it into a hidden input type. Its value will still submit with the Admin panel's requests, but the field itself will not be visible to editors.

Custom components

All Payload fields support the ability to swap in your own React components with ease. For more information, including examples, click here.

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
}

Default values

Fields can be prefilled with starting values using the defaultValue property. This is used in the admin UI and also on the backend as API requests will be populated with missing or undefined field values. You can assign the defaultValue directly in the field configuration or supply a function for dynamic behavior. Values assigned during a create request on the server are added before validation occurs.

Functions are called with an optional argument object containing:

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

Here is an example of a defaultValue function that uses both:

1
const translation: {
2
en: 'Written by'
3
es: 'Escrito por'
4
}
5
6
const field = {
7
name: 'attribution',
8
type: 'text',
9
defaultValue: ({ user, locale }) => `${translation[locale]} ${user.name}`,
10
}

Description

A description can be configured in three ways.

  • As a string
  • As a function which returns a string
  • As a React component

Functions are called with an optional argument object with the following shape, and React components are rendered with the following props:

  • path - the path of the field
  • value - the current value of the field

As shown above, you can simply provide a string that will show by the field, but there are use cases where you may want to create some dynamic feedback. By using a function or a component for the description property you can provide realtime feedback as the user interacts with the form.

Function Example:

1
{
2
fields: [
3
{
4
name: 'message',
5
type: 'text',
6
maxLength: 20,
7
admin: {
8
description: ({ path, value }) =>
9
`${typeof value === 'string' ? 20 - value.length : '20'} characters left (field: ${path})`,
10
},
11
},
12
]
13
}

This example will display the number of characters allowed as the user types.

Component Example:

1
{
2
fields: [
3
{
4
name: 'message',
5
type: 'text',
6
maxLength: 20,
7
admin: {
8
description:
9
({ path, value }) => (
10
<div>
11
Character count:
12
{' '}
13
{ value?.length || 0 }
14
(field: {path})
15
</div>
16
)
17
}
18
}
19
]
20
}

This component will count the number of characters entered, as well as display the path of the field.

TypeScript

You can import the internal Payload Field type as well as other common field types as follows:

1
import type { Field } from 'payload/types'
Next

Array Field