Now.js Framework Documentation
Number Elements
Number Elements
Documentation for NumberElementFactory and CurrencyElementFactory - numeric input components with formatting, validation, and step controls.
📋 Table of Contents
Overview
Number elements handle numeric input with automatic formatting, validation, and keyboard navigation. They convert native <input type="number"> to formatted text inputs for better UX.
| Element | data-element | Description |
|---|---|---|
| NumberElementFactory | number |
Number input with formatting |
| CurrencyElementFactory | currency |
Currency input (2 decimals, grouping) |
Key Features
- ✅ Thousand Separators: Automatic grouping (1,000,000)
- ✅ Decimal Precision: Control decimal places
- ✅ Min/Max Validation: Built-in range validation
- ✅ Step Controls: Arrow keys to increment/decrement
- ✅ Keyboard Filtering: Only allow valid numeric input
- ✅ Paste Validation: Validate pasted content
- ✅ Negative Values: Optional negative number support
- ✅ Currency Symbol: Optional symbol display
NumberElementFactory
NumberElementFactory manages numeric inputs with formatting and validation. It converts the input to type="text" internally to allow formatted display.
Basic Usage
<!-- Simple number input -->
<input type="number"
data-element="number"
name="quantity"
min="0"
max="100">
<!-- Number with formatting -->
<input type="text"
data-element="number"
data-precision="2"
data-use-grouping="true"
name="amount"
placeholder="0.00">HTML Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
data-element |
string | - | Set to number |
min |
number | null |
Minimum allowed value |
max |
number | null |
Maximum allowed value |
step |
number | 1 |
Increment/decrement step |
data-precision |
number | 0 |
Number of decimal places |
data-pad-to-precision |
boolean | false |
Pad with zeros (e.g., 5 → 5.00) |
data-use-grouping |
boolean | false |
Show thousand separators |
data-grouping-separator |
string | , |
Thousand separator character |
data-decimal-separator |
string | . |
Decimal point character |
data-allow-negative |
boolean | false |
Allow negative values |
data-round-values |
boolean | false |
Round to precision |
Configuration Object
NumberElementFactory.config = {
type: 'text',
inputMode: 'decimal',
step: 1,
min: null,
max: null,
precision: 0,
padToPrecision: false,
useGrouping: false,
groupingSeparator: ',',
decimalSeparator: '.',
allowNegative: false,
roundValues: false,
showSymbol: false,
symbol: '',
symbolPosition: 'before',
negativeWithParentheses: false,
validationMessages: {
required: 'Please fill in this field',
min: 'Value must be at least {min}',
max: 'Value must be no more than {max}',
step: 'Value must be a multiple of {step}',
number: 'Please enter a valid number'
}
};Keyboard Navigation
| Key | Action |
|---|---|
ArrowUp |
Increment by step |
ArrowDown |
Decrement by step |
0-9 |
Enter digits |
. or , |
Decimal separator (based on config) |
- |
Negative sign (if allowed, position 0 only) |
Backspace/Delete |
Remove characters |
Input Filtering
NumberElementFactory automatically blocks invalid characters:
// Only these keys are allowed:
// - Digits 0-9
// - Decimal separator (once, if precision > 0)
// - Negative sign (once, at position 0, if allowNegative)
// - Navigation keys (arrows, home, end)
// - Control keys (Ctrl+C, Ctrl+V, etc.)Focus/Blur Behavior
On Focus:
- Formatted value is converted to raw number for easy editing
- Example:
1,234.50→1234.5
On Blur:
- Raw number is reformatted with grouping and padding
- Example:
1234.5→1,234.50
JavaScript API
const instance = ElementManager.getInstance(numberInput);
// Set value programmatically
instance.setValue(1234.56);
// Input shows: 1,234.56 (if useGrouping enabled)
// Parse user input to number
const value = instance.parseNumber('1,234.56');
// Returns: 1234.56
// Format number for display
const formatted = instance.formatNumber(1234.56);
// Returns: '1,234.56'
// Access validation result
const result = instance.validateValue('invalid', true);
// {validatedValue: 'invalid', error: 'Please enter a valid number'}Examples
Integer Only
<input type="number"
data-element="number"
data-precision="0"
name="quantity"
min="1"
max="999">Decimal with 2 Places
<input type="text"
data-element="number"
data-precision="2"
data-pad-to-precision="true"
name="price"
placeholder="0.00">Large Numbers with Grouping
<input type="text"
data-element="number"
data-precision="0"
data-use-grouping="true"
name="population"
placeholder="Enter population">
<!-- User sees: 1,000,000 instead of 1000000 -->Allow Negative Values
<input type="text"
data-element="number"
data-allow-negative="true"
data-precision="2"
name="balance">
<!-- User can enter: -1,234.56 -->CurrencyElementFactory
CurrencyElementFactory extends NumberElementFactory with currency-specific defaults: 2 decimal places, thousand separators, and negative value support.
Basic Usage
<input type="text"
data-element="currency"
name="price"
placeholder="0.00">
<!-- Auto-formatted as: 1,234.56 -->Default Configuration
CurrencyElementFactory.config = {
...NumberElementFactory.config,
precision: 2, // Always 2 decimal places
padToPrecision: true, // Always show .00
roundValues: true, // Round to 2 decimals
showSymbol: false, // No symbol by default
symbol: '', // Add '$' or '฿' as needed
symbolPosition: 'before', // Symbol before number
allowNegative: true, // Allow negative amounts
useGrouping: true, // 1,000,000.00
groupingSeparator: ',',
decimalSeparator: '.',
negativeWithParentheses: false,
inputMode: 'decimal'
};Examples
Basic Currency
<input type="text"
data-element="currency"
name="amount">
<!-- Input: 1234.5 → Display: 1,234.50 -->Thai Baht Format
<input type="text"
data-element="currency"
data-symbol="฿"
data-symbol-position="before"
name="price_thb">
<!-- Display: ฿1,234.50 -->Negative with Parentheses
<input type="text"
data-element="currency"
data-negative-with-parentheses="true"
name="balance">
<!-- Negative display: (1,234.50) instead of -1,234.50 -->No Symbol Display
<input type="text"
data-element="currency"
data-show-symbol="false"
name="amount">
<!-- Just the number: 1,234.50 -->Formatting Options
Precision Examples
| precision | padToPrecision | Input | Output |
|---|---|---|---|
0 |
- | 1234.56 |
1235 |
2 |
false |
1234.5 |
1234.5 |
2 |
true |
1234.5 |
1234.50 |
4 |
true |
1234.1 |
1234.1000 |
Grouping Examples
| useGrouping | groupingSeparator | Input | Output |
|---|---|---|---|
false |
- | 1000000 |
1000000 |
true |
, |
1000000 |
1,000,000 |
true |
1000000 |
1 000 000 |
|
true |
. |
1000000 |
1.000.000 |
Decimal Separator Examples
For European format (comma as decimal):
<input type="text"
data-element="number"
data-decimal-separator=","
data-grouping-separator="."
data-use-grouping="true"
data-precision="2"
name="price">
<!-- Display: 1.234,56 (European format) -->Symbol Position
<!-- Symbol before (default) -->
<input data-element="currency" data-symbol="$">
<!-- Display: $1,234.56 -->
<!-- Symbol after -->
<input data-element="currency" data-symbol="EUR" data-symbol-position="after">
<!-- Display: 1,234.56 EUR -->Events
Standard Events
| Event | When Emitted | Detail |
|---|---|---|
input |
User types | Native event |
change |
Value confirmed | Native event + formatting applied |
focus |
Element focused | Value unformatted for editing |
blur |
Element blurred | Value formatted for display |
Usage Example
const numberInput = document.querySelector('[name="amount"]');
numberInput.addEventListener('change', (e) => {
const instance = ElementManager.getInstance(e.target);
const rawValue = instance.parseNumber(e.target.value);
console.log('Formatted:', e.target.value); // '1,234.56'
console.log('Raw:', rawValue); // 1234.56
});
numberInput.addEventListener('focus', (e) => {
// Value is now unformatted for easy editing
console.log('Editing mode:', e.target.value); // '1234.56'
});
numberInput.addEventListener('blur', (e) => {
// Value is now formatted
console.log('Display mode:', e.target.value); // '1,234.56'
});Best Practices
1. ✅ Use Appropriate Precision
<!-- ✅ Good: Integer for quantities -->
<input data-element="number" data-precision="0" name="quantity">
<!-- ✅ Good: 2 decimals for currency -->
<input data-element="currency" name="price">
<!-- ❌ Bad: Too many decimals for display -->
<input data-element="number" data-precision="10" name="price">2. ✅ Set Min/Max for Validation
<!-- ✅ Good: Prevent invalid ranges -->
<input data-element="number"
min="0"
max="100"
name="percentage">
<!-- ✅ Good: Positive only -->
<input data-element="currency"
min="0"
name="price">3. ✅ Use Currency for Money
<!-- ✅ Good: Currency element for money -->
<input data-element="currency" name="total">
<!-- Automatic: 2 decimals, grouping, negative support -->
<!-- ❌ Bad: Manual configuration -->
<input data-element="number"
data-precision="2"
data-pad-to-precision="true"
data-use-grouping="true"
data-allow-negative="true"
name="total">4. ✅ Use Grouping for Large Numbers
<!-- ✅ Good: Easy to read -->
<input data-element="number"
data-use-grouping="true"
name="population">
<!-- Display: 1,000,000 -->
<!-- ❌ Bad: Hard to count zeros -->
<input data-element="number" name="population">
<!-- Display: 1000000 -->5. ✅ Match Locale Format
<!-- Thai/US format (default) -->
<input data-element="number"
data-decimal-separator="."
data-grouping-separator=",">
<!-- European format -->
<input data-element="number"
data-decimal-separator=","
data-grouping-separator=".">6. ✅ Use Step for Increment Controls
<!-- ✅ Good: Step by 0.5 -->
<input data-element="number"
step="0.5"
min="0"
max="10"
name="rating">
<!-- Arrow keys: 0, 0.5, 1.0, 1.5, ... -->
<!-- ✅ Good: Step by 100 -->
<input data-element="number"
step="100"
min="0"
name="budget">
<!-- Arrow keys: 0, 100, 200, 300, ... -->Related Documentation
- Form Elements Overview
- ElementFactory - Base class
- Text Elements - Text inputs
- Select Elements - Dropdown inputs
- FormManager - Form-level validation