---
title: "Text Field"
aliases: [payload-text-field, text-field-payloadcms, slug-field-payload]
tags: [payloadcms, fields, text, slug, forms]
sources: [raw/fields__text.md]
created: 2026-05-15
updated: 2026-05-15
---

## Overview

The Text Field is one of the most-used Payload fields. It saves a plain `string` to the database and renders a simple text input in the Admin Panel. Set `type: 'text'` in the field config.

```ts
import type { Field } from 'payload'

export const MyTextField: Field = {
  name: 'pageTitle',
  type: 'text',
  required: true,
}
```

## Key Takeaways

- Stores a `string` in the database; one column per field (or multiple rows when `hasMany: true`).
- `hasMany: true` turns it into an **ordered string array** — use `minRows`/`maxRows` to bound it.
- `unique: true` creates a **database-level unique index** — not just an app-level check.
- `saveToJWT: true` embeds the value in the user JWT — useful for roles/flags without extra DB lookups. See [[wiki/payloadcms/authentication-token-data|Authentication — Token Data]].
- `hidden: true` excludes the field from all APIs and the Admin Panel but still persists to DB.
- `virtual: true` (boolean) disables DB persistence; or pass a string path to link to a [[wiki/payloadcms/fields-relationship|Relationship Field]].
- Supports `localized: true` — requires [[wiki/payloadcms/localization|localization enabled]] in root config.
- Built-in **Slug Field** (`slugField()`) is available from `payload` — auto-generates URL-safe slugs from another field, with lock/unlock UI and re-generate button.

## Config Options

| Option | Description |
|--------|-------------|
| `name` * | DB property name |
| `label` | Admin Panel label (string or `{ [lang]: string }`) |
| `unique` | DB-level unique index |
| `minLength` / `maxLength` | Character length validation |
| `validate` | Custom validation function (runs client + server) |
| `index` | Build a DB index for faster queries |
| `saveToJWT` | Include in user JWT (top-level auth fields only) |
| `hooks` | Field lifecycle hooks |
| `access` | Field-level access control |
| `hidden` | Remove from all APIs; still saved to DB |
| `defaultValue` | Default value or function |
| `localized` | Per-locale string values |
| `required` | Non-empty validation |
| `hasMany` | Store as ordered string array |
| `minRows` / `maxRows` | Array bounds when `hasMany: true` |
| `virtual` | Disable DB column (boolean) or link to relationship (path string) |
| `typescriptSchema` | Override generated TS type with JSON schema |

## Admin Options

Extends the base [[wiki/payloadcms/fields-overview|field admin config]] with:

| Option | Description |
|--------|-------------|
| `placeholder` | Placeholder string in the text input |
| `autoComplete` | Browser autocomplete attribute value |
| `rtl` | Force right-to-left text direction (`true`) |

## hasMany Mode

```ts
{
  name: 'tags',
  type: 'text',
  hasMany: true,
  minRows: 1,
  maxRows: 10,
}
```

Stores an ordered array of strings. Each value is a separate DB entry; the order is preserved.

## Built-in Slug Field

Import `slugField` from `payload` to get an auto-generating slug with lock UI:

```ts
import { slugField } from 'payload'

export const PagesCollection: CollectionConfig = {
  slug: 'pages',
  fields: [
    { name: 'title', type: 'text' },
    slugField(),                       // defaults: name='slug', useAsSlug='title'
  ],
}
```

### Slug Config Options

| Option | Default | Description |
|--------|---------|-------------|
| `name` | `'slug'` | Field name |
| `useAsSlug` | `'title'` | Source field to generate slug from |
| `checkboxName` | `'generateSlug'` | Lock/unlock checkbox field name |
| `disableUnique` | `false` | Disable unique index (useful for multi-tenant slugs) |
| `localized` | `false` | Localize both slug and checkbox fields |
| `required` | `true` | Require the slug field |
| `overrides` | — | Function to modify default field definitions |
| `slugify` | — | Override default slugify function |
| `position` | — | Admin Panel position |

### Custom Slugify Function

```ts
import slugify from 'slugify'

slugField({
  slugify: ({ valueToSlugify, data, req }) =>
    slugify(valueToSlugify, { lower: true, strict: true }),
})
```

> **Warning:** The built-in Slug Field is **experimental** and may change or be removed in future releases.

## Custom Components

Payload supports custom Server and Client Components for both the Field and Label slots. Import base components from `@payloadcms/ui` and wrap them.

```tsx
// Server Field component
import { TextField } from '@payloadcms/ui'
import type { TextFieldServerComponent } from 'payload'

export const CustomTextField: TextFieldServerComponent = ({
  clientField, path, schemaPath, permissions,
}) => (
  <TextField field={clientField} path={path} schemaPath={schemaPath} permissions={permissions} />
)
```

See [[wiki/payloadcms/custom-components-authoring|Custom Components — Authoring Guide]] for RSC vs Client rules and Import Map details.

## Related Articles

- [[wiki/payloadcms/fields-overview|Fields Overview]] — shared config: virtual, validation, defaultValue, admin options
- [[wiki/payloadcms/fields-email|Email Field]] — text variant with built-in format validation
- [[wiki/payloadcms/fields-number|Number Field]] — numeric equivalent with `hasMany` support
- [[wiki/payloadcms/fields-select|Select Field]] — enum dropdown (use when values are constrained)
- [[wiki/payloadcms/database-indexes|Database Indexes]] — `unique` and `index` gotchas
- [[wiki/payloadcms/authentication-token-data|Authentication — Token Data]] — `saveToJWT` pattern
- [[wiki/payloadcms/localization|Localization]] — enabling `localized` fields
- [[wiki/payloadcms/custom-components-authoring|Custom Components — Authoring Guide]]

---

*Source: raw/fields__text.md — https://payloadcms.com/docs/fields/text*
