Now.js Framework Documentation

Now.js Framework Documentation

Number Elements

EN 10 Dec 2025 07:02

Number Elements

Documentation for NumberElementFactory and CurrencyElementFactory - numeric input components with formatting, validation, and step controls.

📋 Table of Contents

  1. Overview
  2. NumberElementFactory
  3. CurrencyElementFactory
  4. Formatting Options
  5. Events
  6. Best Practices

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.501234.5

On Blur:

  • Raw number is reformatted with grouping and padding
  • Example: 1234.51,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, ... -->