• CMSnpm version

    • Overview
    • ContentBuilder
    • InviteUserForm
    • LoginForm
    • RenewPasswordForm
    • WysiwygInput
  • UInpm version

    • Overview
    • Accordion
    • AlertBubble
    • AnnouncementBar
    • Avatar
    • AvatarFileInput
    • Badge
    • Button
    • ButtonGroup
    • ButtonList
    • Calendar
    • Checkbox
    • CheckboxButton
    • CheckboxInput
    • CheckboxList
    • Chip
    • ColorRadio
    • ColorRadioGroup
    • Combobox
    • DatePicker
    • DatePickerInput
    • DateRangePicker
    • DateRangePickerInput
    • DatetimePicker
    • DatetimePickerInput
    • Dialog
    • Dropdown
    • Dropzone
    • ErrorMessage
    • FileInput
    • FlashMessages
    • FormComponent
    • Icon
    • IconButton
    • ImageGallery
    • InfoBox
    • Input
    • Label
    • Layout
    • Lightbox
    • ListItem
    • Loader
    • Lozenge
    • Menu
    • Message
    • Modal
    • ✅ ModalDialog
    • ✅ ModalHeader
    • MultiCombobox
    • MultiSelect
    • Pagination
    • Paper
    • Popover
    • Radio
    • RadioGroup
    • RasterImage
    • Select
    • Switch
    • ✅ Tabs
    • TextInput
    • TextLink
    • Textarea
    • TimePicker
    • TimePickerInput
    • Toggle
    • Tooltip
    • Typography
  • Formnpm version

    • Overview
    • AvatarFileInput
    • CheckboxButton
    • CheckboxInput
    • CheckboxList
    • ColorRadioGroup
    • Combobox
    • DatePickerInput
    • DateRangePickerInput
    • DatetimePickerInput
    • Dropzone
    • FileInput
    • Form
    • FormRenderer
    • GpsInput
    • MoneyInput
    • MultiCombobox
    • MultiSelect
    • NumberInput
    • PasswordInput
    • RadioGroup
    • Select
    • TextInput
    • Textarea
    • TimePickerInput
    • Toggle
  • DataGridnpm version

    • Overview
    • DataGrid
    • DataGridCustomExample
    • ExportButton
    • FilterList
    • Filters
    • FiltersButton
    • FulltextInput
    • HiddenColumns
    • HiddenColumnsButton
    • Pagination
    • RowCounts
    • RowsPerPageSelect
    • SelectedRowsToolbar
    • TableV2
    • ToolbarControl
    • ToolbarCustoms
    • ToolbarTabs
  • Wysiwygnpm version

    • Overview
  • Resizernpm version

    • Overview
  • Routernpm version

    • Overview
  • Corenpm version

    • Overview
  • Core-Reactnpm version

    • Overview
  • DnDnpm version

    • Overview
  • Stylesnpm version

    • Overview
  • Localizenpm version

    • Overview
  • Analyticsnpm version

    • Overview
  • Datepickernpm version

    • Overview
  • Icons-generatornpm version

    • Overview
  • Smart-addressnpm version

    • Overview
  • E2Enpm version

    • Overview
  • E2E-Playwrightnpm version

    • Overview
View source on GitLab

MoneyInput

react-hook-form-bound currency field. Renders the @uxf/ui/text-input primitive with type="number", a currency symbol in the rightElement, and stores a Money object, managing the input's value, isInvalid, and helperText from form state.

When to use

Use @uxf/form/money-input for a monetary amount inside a @uxf/form form when the form value must be a Money object ({ amount, currency }), not a bare number. It renders the amount, shows the currency symbol, and tracks the currency. There is no same-named @uxf/ui twin; for a plain numeric field use @uxf/form/number-input.

Usage

import { Form } from "@uxf/form/form";
import { MoneyInput, MoneyInputValue } from "@uxf/form/money-input";
import { useForm } from "react-hook-form";

interface FormData {
    price: MoneyInputValue;
}

function Example() {
    const formApi = useForm<FormData>({ defaultValues: { price: { amount: "100", currency: "USD" } } });

    return (
        <Form formApi={formApi} id="example" onSubmit={(values) => console.log(values)}>
            <MoneyInput control={formApi.control} label="Price" max={200} min={100} name="price" />
        </Form>
    );
}

Value is Money | null (MoneyInputValue), where Money is { amount: string; currency: Currency } from @uxf/core/money. Empty input becomes null; amount is stored as a string, currency defaults to defaultCurrency (or "CZK") until the value sets one.

Amount normalization

While the user types, amount is exactly what they typed — so "1000.00" and "1000" are two different values describing the same money. When the field is left, the amount is snapped to its canonical form via normalizeMoney: "1000.00" becomes "1000", "015" becomes "15", ".5" becomes "0.5". An amount that is not a decimal number becomes null.

This is deliberately on blur rather than on change — on change it would rewrite the text mid-typing and swallow the decimals ("15.5", then typing 0, would be normalized straight back to "15.5").

Without it a Money field reads as dirty forever once the amount is retyped in another notation, because react-hook-form compares the value object leaf by leaf. The component can only canonicalize what it emits — the defaultValues are built by your own mappers, so run them through normalizeMoney too, or the two sides still will not line up:

const formApi = useForm<FormData>({ defaultValues: { price: normalizeMoney(data.price) } });

When the amount is rewritten on blur, the new value is reported through onChange as well (with no event argument), so a consumer keeping its own copy of the value outside react-hook-form stays in sync.

Props

MoneyInputProps<FormData> = ControlProps<FormData> + Omit<TextInputProps, …> + the props below — so the field forwards the @uxf/ui/text-input prop surface apart from the props it manages itself.

Omitted, because this field owns them: inputMode, isFocused, isInvalid, maxLength, minLength, name, onKeyDown, pattern, rightElement, step, type, value — plus min / max / onChange, which are re-declared below with money-specific types.

Beyond the props listed below, everything else on TextInputProps is accepted and forwarded unchanged: autoComplete, autoFocus, className, enterKeyHint, form, hiddenLabel, onBeforeInput, onPaste, placeholder, size, style, variant.

PropTypeDefaultDescription
controlControl<FormData>—Required. The control from useForm.
nameFieldPath<FormData>—Required. Field path in the form values.
rulesRegisterOptions—Extra react-hook-form rules; merged with the built-in validation below.
shouldUnregisterboolean—Unregister the field (drop its value) on unmount.
defaultCurrencyCurrency"CZK"Currency used until the field value carries one; drives the symbol in rightElement.
min / maxnumber—Bounds checked against value.amount by the built-in validMinNumber / validMaxNumber validators.
minMessage / maxMessage(value: MoneyInputValue) => stringlocalizedOverride the min / max validation messages (called with the current value).
isRequiredbooleanfalseAdds a required rule and the required indicator.
requiredMessagestringlocalizedMessage for the required rule.
labelstring—Field label, forwarded to the twin.
helperTextReactNode—Helper text shown when there is no field error.
leftAddon / rightAddon / leftElementReactNode—Forwarded to the twin. rightElement is reserved for the currency symbol.
idstring${formId}__${name}Input id.
onChange(value: MoneyInputValue, event) => void—Called after the field value updates — on every keystroke, and again on blur if the amount was normalized (then without an event).
onBlurFocusEventHandler<HTMLInputElement>—Forwarded to the input; runs after the amount is normalized and the field is marked touched.
onFocusFocusEventHandler<HTMLInputElement>—Accepted, but currently not forwarded to the input, so it never fires. See Gotchas.
isDisabled / isReadOnlybooleaninheritedAlso inherited from the Form.

Gotchas

  • onFocus never fires. It is part of the accepted prop type (via TextInputProps), but the component does not pass it to the rendered input, so the handler is silently dropped. onBlur is unaffected. Use the twin's onFocus directly, or a wrapper, until the passthrough is restored.

Validation

  • isRequired adds a required rule (requiredMessage to override; key uxf-form-money-input:validation.required).
  • min / max compare against value.amount; messages (uxf-form-money-input:validation.min-value / max-value) interpolate {{min}}/{{max}} and are overridable via the minMessage / maxMessage functions.
  • Add further rules via rules (a function validate is merged in under the custom key); the field-level error is shown as the twin's helperText and sets isInvalid.

Requirements

  • Must be rendered inside a Form — it reads the form context (formId, and inherits isDisabled / isReadOnly) and needs a react-hook-form control.
  • Ships no CSS of its own; it renders @uxf/ui/text-input (with the uxf-money-input / uxf-input--no-spin-buttons classes), so include that component's stylesheet(s) and the @uxf/ui token layer — see @uxf/ui/text-input.

Links

  • Rendered primitive: @uxf/ui/text-input
  • Value type: Money / Currency in @uxf/core/money
Default
Open in new tab
States
Open in new tab