textField
A single-line text input. Names, titles, emails, URLs, short codes.
import { textField } from 'nextjs-cms/core/fields'Basic usage
textField({ name: 'title' })That's a complete field: an optional input labelled "Title", stored in a VARCHAR(255) column.
With every option
const title = textField({
// Common options
name: 'title',
label: { en: 'Title', ar: 'العنوان' },
required: true,
defaultValue: 'Untitled',
order: 1,
localized: true,
adminGenerated: true,
conditionalRules: [{ field: kind, condition: 'equals', value: 'article' }],
// textField options
placeholder: 'A short, descriptive title',
minLength: 3,
maxLength: 120,
sanitize: true,
rtl: false,
})Options
| Option | Type | Default | Description |
|---|---|---|---|
placeholder | string | none | Hint shown in the empty input. |
minLength | number | none | Minimum number of characters. Checked on submit. |
maxLength | number | 255 | Maximum number of characters. Also sets the column size: VARCHAR(maxLength). |
defaultValue | string | none | Pre-filled value and column default. |
sanitize | boolean | false | HTML-escape the value before saving. |
rtl | boolean | locale-based | Force the input's text direction. |
Plus the common options: name, label, required, order, conditionalRules, adminGenerated, localized.
Options in detail
maxLength and the column size
maxLength does double duty: it validates input and sizes the column.
textField({ name: 'country_code', maxLength: 2 }) // VARCHAR(2)
textField({ name: 'title' }) // VARCHAR(255)
textField({ name: 'long_title', maxLength: 1000 }) // VARCHAR(1000)Changing it later alters the column, so run update-sections. Shrinking it below existing data's length will fail in MySQL (or truncate, depending on the SQL mode). For text longer than a few thousand characters, use textAreaField (LONGTEXT).
Length checks count JavaScript characters (UTF-16 code units). Most emoji count as 2.
sanitize
Escapes HTML-significant characters (&, <, >, ", ', /, and backtick) before the value is stored.
textField({ name: 'display_name', sanitize: true })| Input | Stored with sanitize: false | Stored with sanitize: true |
|---|---|---|
Tom & Jerry | Tom & Jerry | Tom & Jerry |
<b>Hi</b> | <b>Hi</b> | <b>Hi</b> |
AC/DC | AC/DC | AC/DC |
Leave it off (the default) if your website renders values with React, which escapes on output. Turn it on when the value ends up in raw HTML (email templates, dangerouslySetInnerHTML, legacy PHP pages) and you want the stored value already safe. Don't do both: you would see & on the page.
rtl
By default, the input's direction follows the locale being edited: Arabic content is right-to-left, English left-to-right. rtl pins it regardless of locale:
// Always LTR, even when editing the Arabic translation
textField({ name: 'website_url', rtl: false })
// Always RTL: an Arabic-only field in an otherwise English section
textField({ name: 'arabic_name', rtl: true })defaultValue with adminGenerated: false
A text field hidden from editors is still written on create when it has a default:
textField({ name: 'source', adminGenerated: false, defaultValue: 'cms' })Every item created in the admin gets source = 'cms', while rows your importer writes can use something else.
Examples
Email with a pattern check in a hook
textField has no built-in pattern option. Validate formats in a before hook:
const email = textField({ name: 'email', required: true, maxLength: 254 })
hooks: {
beforeCreate: ({ values }) => {
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(values.email))) {
throw new Error('Please enter a valid email address.')
}
},
}Unique usernames
const username = textField({ name: 'username', required: true, minLength: 3, maxLength: 30 })
db: { table: 'members', unique: [{ columns: [username] }] }As a text identifier
const sku = textField({ name: 'sku', required: true, maxLength: 32 })
db: { table: 'products', identifier: sku }See Database Options.
Storage
| Column | VARCHAR(maxLength ?? 255) CHARACTER SET utf8mb4 |
| Nullable | Yes, unless required (and not conditional) |
| Value | The string as typed (HTML-escaped if sanitize) |