NumberInput
NumberInput
The <NumberInput> component is a form input for entering numeric values. It provides built-in validation and formatting for numbers.
Usage
Use NumberInput in forms for numeric data:
import { Edit, SimpleForm, TextInput, NumberInput } from '@/components/admin';
const ProductEdit = () => (
<Edit>
<SimpleForm>
<TextInput source="name" />
<NumberInput source="price" />
<NumberInput source="stock" />
<NumberInput source="discount" step={0.01} />
</SimpleForm>
</Edit>
);Installation
npx better-admin add number-inputProps
| Prop | Required | Type | Default | Description |
|---|---|---|---|---|
source | Required | string | - | Field name |
label | Optional | string | Inferred | Input label |
placeholder | Optional | string | - | Placeholder text |
helperText | Optional | string | - | Help text below input |
min | Optional | number | - | Minimum value |
max | Optional | number | - | Maximum value |
step | Optional | number | 1 | Step increment |
required | Optional | boolean | false | Mark as required |
disabled | Optional | boolean | false | Disable input |
readOnly | Optional | boolean | false | Read-only mode |
validate | Optional | Validator[] | - | Validation rules |
Min and Max Values
Set bounds for the input:
<NumberInput source="age" min={0} max={120} />
<NumberInput source="rating" min={1} max={5} />
<NumberInput source="quantity" min={0} />Step Increment
Control the increment step:
<NumberInput source="price" step={0.01} /> {/* Decimals */}
<NumberInput source="quantity" step={1} /> {/* Integers */}
<NumberInput source="discount" step={5} /> {/* Steps of 5 */}With Validation
Add validation rules:
import { required, min, max, number } from '@/lib/validators';
<NumberInput
source="price"
validate={[
required('Price is required'),
min(0, 'Price must be positive'),
max(10000, 'Price too high')
]}
step={0.01}
/>Helper Text
Add context about the input:
<NumberInput
source="stock"
helperText="Current inventory level"
min={0}
/>
<NumberInput
source="discount_percent"
helperText="Enter percentage (0-100)"
min={0}
max={100}
/>Required Fields
Mark fields as required:
<NumberInput source="price" required min={0} />
<NumberInput source="quantity" required min={1} />With better-query
NumberInput integrates with better-query:
import { Edit, SimpleForm, TextInput, NumberInput } from '@/components/admin';
import { useQuery } from 'better-admin';
import { query } from '@/lib/query';
export function ProductEdit({ id }: { id: string }) {
const { data, update } = useQuery("product", query);
return (
<Edit
resource="product"
id={id}
onSubmit={(values) => {
update.mutate({
where: { id },
data: values,
});
}}
>
<SimpleForm>
<TextInput source="name" required />
<TextInput source="sku" />
<NumberInput
source="price"
step={0.01}
min={0}
required
helperText="Price in USD"
/>
<NumberInput
source="stock"
min={0}
required
/>
<NumberInput
source="discount_percent"
min={0}
max={100}
helperText="Discount percentage (0-100)"
/>
</SimpleForm>
</Edit>
);
}Currency Input
Create a currency input wrapper:
import { NumberInput } from '@/components/admin';
export function CurrencyInput({ source, ...props }: any) {
return (
<NumberInput
source={source}
step={0.01}
min={0}
{...props}
format={(value) => value ? `$${value.toFixed(2)}` : ''}
parse={(value) => parseFloat(value.replace('$', '')) || 0}
/>
);
}Percentage Input
<NumberInput
source="tax_rate"
min={0}
max={100}
step={0.1}
helperText="Tax rate percentage"
suffix="%"
/>Complete Example
import {
Create,
SimpleForm,
TextInput,
NumberInput,
SelectInput,
} from '@/components/admin';
import { useQuery } from 'better-admin';
import { query } from '@/lib/query';
import { required, min } from '@/lib/validators';
export function ProductCreate() {
const { create } = useQuery("product", query);
return (
<Create
resource="product"
onSubmit={(values) => {
create.mutate({ data: values });
}}
>
<SimpleForm>
<TextInput
source="name"
validate={required()}
required
/>
<TextInput
source="sku"
validate={required()}
helperText="Unique product identifier"
/>
<NumberInput
source="price"
step={0.01}
min={0}
validate={[required(), min(0.01, 'Price must be greater than 0')]}
required
helperText="Price in USD"
/>
<NumberInput
source="cost"
step={0.01}
min={0}
helperText="Cost per unit"
/>
<NumberInput
source="stock"
min={0}
validate={[required(), min(0)]}
required
helperText="Available inventory"
/>
<NumberInput
source="weight"
step={0.01}
min={0}
helperText="Weight in kg"
/>
<NumberInput
source="discount_percent"
min={0}
max={100}
step={1}
helperText="Discount percentage (0-100)"
/>
<SelectInput
source="status"
choices={[
{ id: 'active', name: 'Active' },
{ id: 'inactive', name: 'Inactive' },
]}
required
/>
</SimpleForm>
</Create>
);
}Format and Parse
Custom formatting and parsing:
<NumberInput
source="phone"
format={(value) => {
// Format for display
return value?.toString().replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
}}
parse={(value) => {
// Parse for storage
return parseInt(value.replace(/\D/g, ''));
}}
/>Integer Only
Restrict to integers:
<NumberInput
source="quantity"
step={1}
validate={[
required(),
(value) => Number.isInteger(value) || 'Must be an integer'
]}
/>Related Components
- TextInput - Text input
- SelectInput - Select dropdown
- NumberField - Display numbers