numberField
Integers and decimals with range checks. The column type is chosen from the range you declare.
import { numberField } from 'nextjs-cms/core/fields'Basic usage
numberField({ name: 'quantity' })An integer input stored in an INT(11) column.
With every option
numberField({
name: 'price',
label: { en: 'Price (USD)', ar: 'السعر' },
required: true,
order: 3,
localized: false,
adminGenerated: true,
conditionalRules: [{ field: isPaid, condition: 'equals', value: true }],
format: 'float',
placeholder: '0.00',
minValue: 0,
maxValue: 99_999.99,
minLength: 1,
maxLength: 8,
defaultValue: 0,
rtl: false,
})Options
| Option | Type | Default | Description |
|---|---|---|---|
format | 'int' | 'float' | 'double' | 'bigint' | 'int' | Number kind, and the column type family. |
minValue | number | none | Smallest allowed value. minValue >= 0 also makes the column UNSIGNED. |
maxValue | number | none | Largest allowed value. |
minLength | number | none | Minimum number of digits (length of the value as a string). |
maxLength | number | none | Maximum number of digits. For integers, also the column display width. |
placeholder | string | none | Hint in the empty input. |
defaultValue | number | none | Pre-filled value and column default. |
rtl | boolean | locale-based | Force the input direction. |
hasAutoIncrement | true | false | Auto-increment mode. See below. |
Plus the common options. The field throws on load if minValue > maxValue or minLength > maxLength.
Options in detail
format
format | Accepts | Column |
|---|---|---|
'int' (default) | Whole numbers | Smallest integer type that fits the range (see below) |
'bigint' | Whole numbers beyond ±2.1 billion | BIGINT |
'float' | Decimals, ~7 significant digits | FLOAT |
'double' | Decimals, ~15 significant digits | DOUBLE |
numberField({ name: 'rating', format: 'double', minValue: 0, maxValue: 5 })
numberField({ name: 'population', format: 'bigint', minValue: 0 }) // BIGINT UNSIGNEDFLOAT and DOUBLE are binary floating-point: 0.1 + 0.2 isn't exactly 0.3. For money, store integer cents (numberField({ name: 'price_cents', minValue: 0, maxValue: 100_000_000 })) and format on display.
How integer columns are sized
For format: 'int', the column is the smallest MySQL integer type that fits minValue/maxValue (or maxLength digits when no bounds are given). With no bounds at all, it's INT.
| Field | Column |
|---|---|
numberField({ name: 'n' }) | INT(11) |
numberField({ name: 'age', minValue: 0, maxValue: 150 }) | TINYINT UNSIGNED |
numberField({ name: 'year', minValue: 1900, maxValue: 2100 }) | SMALLINT UNSIGNED |
numberField({ name: 'delta', minValue: -1000, maxValue: 1000 }) | SMALLINT |
numberField({ name: 'stock', minValue: 0, maxValue: 1_000_000 }) | MEDIUMINT UNSIGNED |
numberField({ name: 'zip', maxLength: 5 }) | MEDIUMINT(5) (up to 99,999) |
A missing bound is treated as "no constraint", so the smallest type wins. numberField({ name: 'views', minValue: 0 }) becomes TINYINT UNSIGNED, which caps at 255. Whenever you set minValue, also set a realistic maxValue (or leave both out to get INT).
Changing bounds later can change the column type; update-sections handles the ALTER.
minLength / maxLength: digit counts
These check the number of characters in the value, not its size. Useful for fixed-width codes:
// Exactly 6 digits: 100000–999999
numberField({ name: 'pin', minLength: 6, maxLength: 6 })For codes with leading zeros (007, ZIP codes like 02134), use a textField instead: numbers drop leading zeros.
Auto-increment
numberField({ name: 'ticket_no', hasAutoIncrement: true })In auto-increment mode, MySQL assigns the value:
- The field is forced to
adminGenerated: false(hidden on create, not submitted). formatcan only be'int'(or omitted).placeholder,minValue,maxValue,minLength,maxLength,defaultValueandadminGeneratedare not allowed; TypeScript and runtime validation reject them.
The default section identifier is exactly this: numberField({ name: 'id', required: true, hasAutoIncrement: true }). MySQL allows one auto-increment column per table, so don't add another when using the default identifier.
adminGenerated: 'readonly' counters
A column your website updates, visible to editors:
numberField({ name: 'download_count', label: 'Downloads', adminGenerated: 'readonly' })Examples
Manual sort position
const position = numberField({ name: 'position', minValue: 0, maxValue: 10_000, defaultValue: 0 })
db: { table: 'slides', orderByField: position }Percentages
numberField({ name: 'discount_percent', minValue: 0, maxValue: 100, defaultValue: 0 })
// → TINYINT UNSIGNEDCoordinates without a map
numberField({ name: 'lat', format: 'double', minValue: -90, maxValue: 90 })
numberField({ name: 'lng', format: 'double', minValue: -180, maxValue: 180 })Storage
| Column | Integer type sized from the range, BIGINT, FLOAT, or DOUBLE; UNSIGNED when minValue >= 0 |
| Value | A number |