Atlas Forms
Number Input
The number type renders a numeric input with built-in range validation, configurable precision, step controls, and optional currency or percentage formatting. The stored value is always a JavaScript number, never a string.
Minimal Example
{
"id": "quantity",
"type": "number",
"label": "Quantity",
"required": true,
"width": "third",
"binding": {
"source": "$json",
"path": "order.quantity"
}
}
Settings Reference
| Setting | Type | Default | Description |
|---|---|---|---|
min | number | — | Minimum allowed value (inclusive) |
max | number | — | Maximum allowed value (inclusive) |
step | number | 1 | Increment amount for spinner up/down buttons |
precision | number | — | Number of decimal places to display and accept |
format | none | currency | percent | none | Display formatting applied in view mode and on blur |
currency | string (ISO 4217) | USD | Currency code used when format: "currency" |
locale | string (BCP 47) | browser locale | Locale for number formatting (comma/period separators) |
showSpinner | boolean | true | Show increment/decrement arrows on the input |
placeholder | string | — | Placeholder text shown when empty |
prefix | string | — | Static label before input (e.g., $) |
suffix | string | — | Static label after input (e.g., kg, %) |
Range and Step Validation
{
"id": "age",
"type": "number",
"label": "Age",
"settings": {
"min": 18,
"max": 120,
"step": 1,
"placeholder": "Enter your age"
},
"validation": {
"required": true,
"min": 18,
"max": 120
}
}
Settings vs Validation
min/max in settings constrains the spinner buttons and HTML input attributes. The same values in validation trigger the validation engine with an error message. Set both to ensure complete enforcement.
Currency Formatting
When format: "currency" is set, the value is formatted on blur and in view mode using the browser's Intl.NumberFormat API. The stored value remains a plain number (not a formatted string):
{
"id": "invoice-amount",
"type": "number",
"label": "Invoice Amount",
"width": "half",
"settings": {
"format": "currency",
"currency": "USD",
"locale": "en-US",
"precision": 2,
"min": 0,
"prefix": "$"
},
"binding": {
"source": "$json",
"path": "invoice.amount"
}
}
// User types: 1500
// Displayed on blur: $1,500.00
// Stored value: 1500
Percentage Format
{
"id": "tax-rate",
"type": "number",
"label": "Tax Rate",
"width": "third",
"settings": {
"format": "percent",
"precision": 2,
"min": 0,
"max": 100,
"suffix": "%"
}
}
// User types: 8.5
// Displayed: 8.50%
// Stored: 8.5
Decimal Precision
| Use Case | precision | step |
|---|---|---|
| Whole numbers (count, quantity) | 0 | 1 |
| Currency (USD, EUR) | 2 | 0.01 |
| Scientific / high accuracy | 6 | 0.000001 |
| Percentage | 2 | 0.01 |
| Weight (kg with grams) | 3 | 0.001 |
Quick-Pick Integration
The number input is commonly used in the Quick-Pick pattern alongside a select dropdown. See the Quick-Pick Pattern guide for a complete example. The core idea: a select with preset values and a number manual override share the same binding.path. Last-write-wins.
Full Example — Product Line Item
{
"id": "unit-price",
"type": "number",
"label": "Unit Price",
"width": "third",
"order": 2,
"settings": {
"format": "currency",
"currency": "USD",
"precision": 2,
"min": 0,
"showSpinner": false
},
"validation": {
"required": true,
"min": 0
},
"binding": {
"source": "$json",
"path": "lineItem.unitPrice"
}
},
{
"id": "quantity",
"type": "number",
"label": "Qty",
"width": "third",
"order": 3,
"settings": {
"min": 1,
"max": 9999,
"step": 1,
"precision": 0
},
"validation": {
"required": true,
"min": 1
},
"binding": {
"source": "$json",
"path": "lineItem.quantity"
}
}