A form-associated custom element for currency input. Displays a locale-aware currency symbol prefix, formats the value on blur (e.g. 1,234.56), and shows the raw numeric value on focus for editing. Integrates with x-form via ElementInternals.
<x-currency-field></x-currency-field>
| Attribute | Type | Default | Notes |
|---|---|---|---|
name | string | "" | Form field name |
value | string | "" | Raw numeric string, e.g. "1234.56" |
currency | string | "USD" | ISO 4217 code; uppercased; falls back to "USD" |
locale | string | "" | BCP 47 tag for formatting; "" uses browser default |
min | string | "" | Minimum numeric value (triggers rangeUnderflow) |
max | string | "" | Maximum numeric value (triggers rangeOverflow) |
placeholder | string | "" | Input placeholder text |
label | string | "" | Label text (shown above input; hidden when empty) |
hint | string | "" | Helper text shown below the input |
error | string | "" | Custom error message (triggers customError validity) |
disabled | boolean | absent | Disables the input |
required | boolean | absent | Marks as required for form validation |
readonly | boolean | absent | Makes the input read-only |
All properties reflect to/from their corresponding attributes.
| Property | Type | Reflects attribute |
|---|---|---|
value | string | value |
name | string | name |
currency | string | currency |
locale | string | locale |
min | string | min |
max | string | max |
placeholder | string | placeholder |
label | string | label |
hint | string | hint |
error | string | error |
disabled | boolean | disabled |
required | boolean | required |
readOnly | boolean | readonly |
The value getter always returns the raw numeric string stored in the value attribute (not the formatted display value).
| Event | Bubbles | Composed | Cancelable | Detail |
|---|---|---|---|---|
x-currency-field-input | yes | yes | no | { name: string, value: string } |
x-currency-field-change | yes | yes | no | { name: string, value: string } |
value in the event detail is always the raw numeric string (what will be submitted with the form). On x-currency-field-change, the value is canonicalized via parseFloat (e.g. "1234.5" not "1,234.50").
:host
style
div[part=field]
label[part=label] — hidden via .label-hidden when empty
div[part=input-wrapper]
span[part=symbol] — currency symbol extracted via Intl (e.g. "$")
input[part=input] — type="text", inputmode="decimal"
span[part=hint] — hidden via .hint-hidden when empty
span[part=error] — role=alert, aria-live=assertive; hidden via .error-hidden
| Property | Default (light) | Default (dark) |
|---|---|---|
--x-currency-field-bg | #ffffff | #1f2937 |
--x-currency-field-color | #111827 | #f9fafb |
--x-currency-field-border | 1px solid #d1d5db | 1px solid #4b5563 |
--x-currency-field-border-radius | 6px | 6px |
--x-currency-field-focus-ring-color | #2563eb | #3b82f6 |
--x-currency-field-symbol-color | #6b7280 | #9ca3af |
--x-currency-field-label-color | #374151 | #d1d5db |
--x-currency-field-hint-color | #6b7280 | #9ca3af |
--x-currency-field-error-color | #dc2626 | #f87171 |
--x-currency-field-disabled-opacity | 0.45 | 0.45 |
| State | Condition |
|---|---|
customError | error attribute is set and non-empty |
valueMissing | required is set and value is empty |
badInput | value is non-empty but not a valid number |
rangeUnderflow | value parses to a number less than min (when min is set) |
rangeOverflow | value parses to a number greater than max (when max is set) |
x-currency-field is a form-associated custom element (static formAssociated = true). It integrates with native <form> elements and with x-form via ElementInternals:
formDisabledCallback — sets/removes the disabled attribute and re-rendersformResetCallback — clears the value attribute and the input display"1234.56")input.value shows the value formatted with Intl.NumberFormat (e.g. "1,234.56" for USD/en-US)input.value shows the raw numeric string (e.g. "1234.56") so the user can edit it naturallyparseFloat and stored as the value attribute; the display is reformattedThe currency symbol is displayed in span[part=symbol] and is never included in the input value.
label[part=label] is associated with input[part=input] via for/idinput has aria-labelledby="label", aria-required, aria-invalid, and aria-describedby (points to hint/error when present)span[part=error] has role="alert" and aria-live="assertive"span[part=symbol] has aria-hidden="true"input has inputmode="decimal" for numeric keyboard on mobile<x-currency-field
name="price"
label="Price"
currency="USD"
placeholder="0.00"
></x-currency-field>
<x-currency-field
name="amount"
label="Amount"
value="1234.56"
currency="USD"
></x-currency-field>
<x-currency-field
name="budget"
label="Budget"
required
min="0"
max="10000"
hint="Enter a value between $0 and $10,000"
></x-currency-field>
<x-currency-field
name="price"
label="Preis"
currency="EUR"
locale="de-DE"
value="1234.56"
></x-currency-field>
<!-- displays: 1.234,56 with € symbol -->
<x-form>
<x-currency-field
name="price"
label="Product price"
required
currency="USD"
></x-currency-field>
<button type="submit">Submit</button>
</x-form>
The submitted FormData will contain price=1234.56 (raw numeric string).
const field = document.querySelector('x-currency-field');
// Read current value (raw numeric string)
console.log(field.value); // "1234.56"
// Set value programmatically
field.value = "999.99";
// Listen to events
field.addEventListener('x-currency-field-change', e => {
console.log(e.detail.value); // "999.99"
});
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |