Currency In Any Locale
Give it an ISO 4217 code and the number is money: the symbol lands where that locale puts it, with that locale's separators and the currency's own decimal places.
NWD Number Input (Currency & Units) was built to replace the number formats of Bubble’s native input, from integer and decimal to currency and percentage, and adds units of your own, offering far more styling and formatting flexibility and control. It brings currency formatting for any currency, a cash-register style mask, range limits, and stepper buttons together in one polished component. Fully customizable through 40+ properties, giving you complete control over every visual and behavioral detail.
Built for what Bubble does not cover.
Bubble's native number field is not a dedicated input. It is one content format of a generic input that also does text, email, password and phone, and the formatting it offers stops where most forms start: there is no symbol placed by the visitor's locale, no thousands grouping that keeps up while the person types, no unit after the number, and no stepper. Anything beyond that is built by hand, with a group, a text element and a workflow per button, and the value you store ends up shaped by whatever the person typed.
Give it an ISO 4217 code and the number is money: the symbol lands where that locale puts it, with that locale's separators and the currency's own decimal places.
Text before and after the number, for a symbol or a unit like kg, km or %, drawn inside the field and never mixed into the value.
Decimal places, a minimum and a maximum, and your choice of what happens outside them: pull the value to the nearest limit, or keep it and mark the field invalid.
Minus and plus buttons at both ends of the field or stacked at one end, with four icon sets, and the same step on the arrow keys, times ten with Shift.
The field, the icon from twelve choices, the prefix and suffix, the stepper and its hover, plus the disabled, invalid and focused states, are all yours to style.
Announced as a spin button with its current value and its limits, operable from the keyboard, with a name and a hint you can write yourself.
In detail
Place the plugin element wherever you need it.
Adjust the settings to match your use case, including the currency, the range, the precision, and the stepper.
Use the value changed event to capture the confirmed number and read the exposed states to use them anywhere in your app.
Text displayed in the input while it has no value.
Color of the placeholder text.
Whether the browser can suggest saved values.
Text shown before the number, such as a currency symbol. It is not part of the value.
Text shown after the number, such as a unit (kg, km, %). It is not part of the value.
Controls whether the input icon is displayed.
Icon displayed in the input.
Icon size in pixels. When empty, it is calculated from the input font size.
Color of the input icon.
Whether the icon appears to the left or right of the input text.
Lowest accepted value. Leave empty for no limit.
Highest accepted value. Leave empty for no limit.
What happens when the value leaves the range: clamp adjusts it to the nearest limit when leaving the input, and right away when the limits change; invalid keeps it and marks the input as invalid.
Amount added or subtracted by the stepper buttons and the arrow keys (Shift multiplies by 10).
The step is what the arrow keys and the stepper buttons add or subtract. Holding Shift multiplies it by ten, so a step of 1 moves in tens and a step of 0.5 moves in fives.
Number of decimal places accepted and displayed, from 0 to 10. With a currency code, 0 uses the currency’s own decimal places.
It governs both what is accepted and what is displayed: a value with more decimals is rounded to this many on arrival, whether it comes from the default value, from typing or from the Set value action.
BCP 47 locale that defines the decimal and thousands separators (for example en-US or pt-BR). When empty or invalid, uses the browser locale.
Leave it empty and each visitor sees the number in their own browser's convention, which is what a public form usually wants. Fill it to pin one convention for everyone, as in an internal tool whose numbers are read side by side.
ISO 4217 code (BRL, USD, EUR). When filled, the number is shown as money, with the symbol placed by the locale; decimal places follow the currency unless Decimal places is set. Leave the prefix empty when using it.
The code also decides the decimal places when Decimal places is 0, because that is part of the currency: two for `BRL` and `USD`, none for `JPY`. An invalid or empty code simply means no currency, and the number is shown plain.
Typing fills the number from the last decimal place, like a cash register (1 > 0.01, 12 > 0.12, 123 > 1.23). Requires decimal places or a currency.
With the mask on, the field is always formatted, including while the person types, and only digits are accepted. Without decimal places there is nothing to fill from, so set Decimal places before turning it on.
Groups the thousands with the locale’s separator.
Shows the increment and decrement buttons.
Where the stepper buttons go: both (minus at the left end, plus at the right end), left or right (both stacked at that end, plus on top).
Icons of the stepper buttons.
Icon size in pixels. When empty, it is calculated from the input font size.
Corner radius, in pixels, of the background behind each stepper button.
Color of the stepper icons.
Stepper button background color. When empty, the button has no background until hovered.
Color of the stepper icons when hovered.
Stepper button background color on hover.
Also triggers Value changed as the user types or uses the arrow keys. Unchecked, it triggers on leaving the input, on Enter and on each stepper click.
A search bound to this element's value already updates as the person types, without this option. Check it when the filter, autosave or counter runs through a workflow.
Value applied on load and on reset.
It keeps following its source until the person interacts with the field, so a value loaded later or changed by a condition still reaches the input, and it does so without firing `value changed`. After the first interaction the field belongs to the person, and only Reset or Set value writes into it.
Disables the component, preventing any interaction.
Input background color when disabled.
Input border color when disabled.
Input font color when disabled.
Marks the field as required and enables input validation.
Input background color when invalid.
Input border color when invalid.
Input background color when focused.
Input border color when focused.
Name read by screen readers. When empty, uses the placeholder or the visible label.
Hint read by screen readers after the name. Empty for none.
Values the element exposes for the rest of the page to read.
Store value, which is the number and nothing else, and show value (formatted), which is the text the person sees with the prefix, the separators and the suffix. Saving the formatted text into a number field is the one mistake this pair exists to prevent.
With Out of range behavior set to clamp, a typed number is pulled back into the range, so it never makes the input invalid. Set it to invalid to keep the typed number and flag it instead.
Every state updates on each keystroke, so texts, conditions and searches bound to it react as the person types, with no workflow and without waiting for the field to lose focus. For a database search over a large list, consider feeding it from the value changed event instead, so the search runs once per pause or on confirming rather than on every keystroke.
Current number. Empty when the input is empty.
Number as displayed, including the prefix and suffix.
True when the value is outside the minimum and maximum.
The locale that actually applied: the Locale field when it is valid, or the visitor's browser language when the field is empty or its form is not recognised.
True when the component is not disabled.
True when the input is marked as required.
True when the value is accepted. False when it is required and empty, or the number is out of range while Out of range behavior is set to invalid. It updates on every change, so a workflow can rely on it; the invalid style only shows after the person leaves the field, or when a workflow sets the value.
True while the input has focus.
Where a workflow can start.
Triggered when the value is confirmed with a different number: leaving the input, pressing Enter, using the stepper, resetting, or when a change to the range pulls a value that was already chosen back into it. With Trigger value changed while typing checked, typing and the arrow keys also trigger it.
What a workflow can tell the element to do.
Restores the default value, or clears the input when there is none.
Focuses the number input.
Writes a number into the field from a workflow, applying the configured range and decimals, and refreshes the exposed states.
Yes applies the value even while the element is disabled. No makes the action do nothing in that state.
The value to write into the field. It goes through the same treatment as a value typed by the user. An empty value clears the field.
Two values and five flags. `value` is the number itself, ready for a database field of type number, and `value (formatted)` is the text the person sees, prefix and suffix included (`R$ 1.234,50 /month`). `is valid`, `is out of range`, `is required`, `is clickable` and `is focused` cover the state of the field. The `value changed` event fires when the value is confirmed, which means leaving the field, pressing Enter, clicking the stepper or running Reset. With Trigger value changed while typing? checked, it also fires as the person types or uses the arrow keys. It also fires when a change to the range pulls a number that was already chosen back into it.
Fill Currency code with an ISO 4217 code (`BRL`, `USD`, `JPY`) and the number is shown as money. The symbol goes where the locale puts it, before or after, with that locale's separators, and when Decimal places is left at 0 the currency decides them: two for BRL and USD, none for JPY. Locale is what picks the convention; leave it empty and the visitor's browser decides.
Currency mask (fill from cents)? makes typing work like a cash register: the digits fill the number from the last decimal place, so 1 becomes 0.01, 12 becomes 0.12 and 123 becomes 1.23, with the cursor always at the end. It does not need a currency, only decimal places, so it works for any measurement typed from the smallest unit up.
That is yours to choose in Out of range behavior. With `clamp`, the value is pulled to the nearest limit when the person leaves the field, or right away when the minimum or maximum changes, and the stepper arrow that has reached its limit fades out. With `invalid`, the number is kept as typed, the field takes the invalid styling, `is valid` turns no and `is out of range` turns yes, so a workflow can block the submit and say why.
Yes, with the Set value action, which puts the number through the same path as typing: decimal places, currency and the range rule all apply, the states are republished and `value changed` fires. It carries Apply even when disabled?, so a disabled field can still be filled by your workflow when you mean it to be. Reset returns to the default value and Focus puts the cursor in the field.
No. The thousands separator stays while the person types, regrouping with each digit and keeping the cursor after the digit just typed; Backspace right after a separator removes the digit before it. The currency symbol steps aside on focus and comes back on leaving, unless the currency mask is on, where the formatting is the typing. Typing accepts the decimal separator as a dot or a comma, whichever the locale uses, and a minus sign only when the minimum allows negatives.
This plugin is maintained by GCS Studios and is part of the NWD UI - Input family, form controls built from scratch for Bubble, inspired by a personal component library originally built for React. Each one is carefully designed and tested in real applications before release, for the level of control, polish and reliability that native Bubble inputs often do not provide. See more plugins on the GCS Studios contributor page.
Each control here is drawn by the plugin instead of being restyled from a native one, so they match each other across the library and keep the same shape in every browser.