HEEx components for locale-aware form input.
Today: number_input/1. More inputs (percentage, ratio,
dimension, …) will land here over time under the same
namespace.
Setup
Add the JS hook in your assets/js/app.js:
import Hooks from "localize_inputs"
let liveSocket = new LiveSocket("/live", Socket, {
hooks: { NumberInput: Hooks.NumberInput }
})Install AutoNumeric as a peer dep:
npm install autonumericTolerance of invalid input
These components sit on the render path and never raise on bad input — the page always renders. Specifically:
Unknown
:locale— falls back to:enlocale data; if:enitself is unavailable (broken Localize install) falls back to an empty%Localize.Inputs.Number.Symbols{}so attribute reads still resolve to safe defaults.Unknown
:categoryonunit_input/1— falls back to an empty%Localize.Inputs.Number.Unit{}. The picker renders no rows rather than 500ing the page.Blank or non-numeric
value— formatted as""in the visible input; the hidden ISO carrier stays empty. The submit-side parser (Localize.Inputs.Number.Parser.parse_number/2) returns{:ok, nil}for blanks and{:error, _}for garbage, never raises.Malformed
:min/:max/:decimalsbounds —Localize.Inputs.Number.Validator.validate_number/2usesDecimal.parse/1with aDecimal.new(0)fallback, so a typo in a bound silently passes the bound check rather than crashing the validation pipeline. Returns{:error, %ValidationError{}}for real out-of-range values.
Summary
Functions
Locale-aware plain-number input.
Locale-aware number + unit-of-measure input.
Standalone locale-aware unit picker.
Functions
Locale-aware plain-number input.
Renders an <input type="text" inputmode="decimal"> wrapped
in a <div> that carries data- attributes the JS hook
reads (locale, separators, minus sign, min/max, decimals).
With AutoNumeric loaded the input live-formats as the user
types; without it, the server-side parser
(Localize.Inputs.Number.Parser.parse_number/2) accepts whatever
the user typed on submit.
The form value submits in the user's locale-formatted shape
— exactly what AutoNumeric was displaying. Parse it on the
server with Localize.Inputs.Number.Parser.parse_number/2 (or
Localize.Inputs.Number.Changeset.validate_number/3 for an
Ecto-backed flow). One wire shape regardless of whether the
JS hook is loaded — no canonical-vs-locale ambiguity.
Arguments
assigns— see the per-attribute documentation below.
Attributes
:form— thePhoenix.HTML.Formthe field belongs to.:field— the form field as an atom.:locale— display locale. Defaults toLocalize.get_locale/0.:integer— whentrue, accept integers only and emitinputmode="numeric".:min,:max— value bounds.:decimals— maximum fractional digits.:align—:left(default),:right, or:center.:placeholder— placeholder text.:js— set tofalseto skip thephx-hookattribute.:class,:input_class— extra classes for the wrapper and the input.
Returns
- A
Phoenix.LiveView.Renderedstruct containing the input markup.
Examples
<.number_input form={@form} field={:quantity} integer={true} min={1} max={999} />
<.number_input form={@form} field={:rating} min={0} max={5} decimals={1} />Attributes
form(Phoenix.HTML.Form) (required)field(:atom) (required)value(:any) - Defaults tonil.locale(:string) - Defaults tonil.integer(:boolean) - Defaults tofalse.min(:any) - Defaults tonil.max(:any) - Defaults tonil.decimals(:integer) - Defaults tonil.align(:atom) - Defaults to:left. Must be one of:left,:right, or:center.placeholder(:string) - Defaults tonil.js(:boolean) - Defaults totrue.class(:string) - Defaults tonil.input_class(:string) - Defaults tonil.- Global attributes are accepted. Supports all globals plus:
["disabled", "readonly", "required", "autofocus"].
Locale-aware number + unit-of-measure input.
Renders a number input paired with a searchable
unit_picker/1 for a given measurement category
("length", "volume", "mass", …). The picker is
grouped into Preferred (units in the locale's
measurement system — metric, US, or UK) and All units
(every known unit in the category). Unit display names are
localized via Localize.Unit.display_name/2.
Submits as a nested map:
params[field] = %{"amount" => "1.5", "unit" => "meter"}Parse on the server with the locale you already have.
Attributes
:form— thePhoenix.HTML.Formthe field belongs to.:field— the form field as an atom. The amount and unit sub-fields submit underparams[field][amount]andparams[field][unit].:category— the unit category as a string (e.g."length"). Required. SeeLocalize.Inputs.Number.Unit.known_categories/0.:default_unit— the unit selected by default. Ifnil, the first preferred unit for the locale is selected.:locale— display locale. Defaults toLocalize.get_locale/0.:integer,:min,:max,:decimals,:align,:placeholder,:js,:class,:input_class— passed through to the underlyingnumber_input/1.:include_prefixed— whentrue, the All-units section includes SI-prefixed variants (e.g.decimeter). The default isfalseto keep the list manageable.
Examples
<.unit_input form={@form} field={:height} category="length" />
<.unit_input
form={@form}
field={:weight}
category="mass"
default_unit="kilogram"
min={0}
/>Attributes
form(Phoenix.HTML.Form) (required)field(:atom) (required)category(:string) (required)default_unit(:string) - Defaults tonil.locale(:string) - Defaults tonil.value(:any) - Defaults tonil.integer(:boolean) - Defaults tofalse.min(:any) - Defaults tonil.max(:any) - Defaults tonil.decimals(:integer) - Defaults tonil.align(:atom) - Defaults to:left. Must be one of:left,:right, or:center.placeholder(:string) - Defaults tonil.include_prefixed(:boolean) - Defaults tofalse.js(:boolean) - Defaults totrue.class(:string) - Defaults tonil.input_class(:string) - Defaults tonil.picker_class(:string) - Defaults tonil.- Global attributes are accepted. Supports all globals plus:
["disabled", "readonly", "required", "autofocus"].
Standalone locale-aware unit picker.
Searchable picker grouped into a Preferred section
(units in the locale's measurement system) and an
All units section (every known unit in the category).
Selecting a row updates a hidden input that the picker
serialises on form submission and emits a
localize-inputs:unit-change CustomEvent so any enclosing
unit_input/1 can react.
Attributes
:current— the currently-selected unit name (string). Required.:category— the unit category. Required.:locale— display locale. Defaults toLocalize.get_locale/0.:form+:field— when given, the hidden value input is namedPhoenix.HTML.Form.input_name(form, field).:name— explicit hidden-input name. Overrides:form/:field. Used byunit_input/1to inject a nested name likeheight[unit].:input_id— explicit id for the hidden value input.:include_prefixed— whentrue, the All-units section includes SI-prefixed variants.:variant—:auto(default),:dropdown, or:sheet.:id,:class,:button_class,:overlay_class,:row_class— customisation hooks.
Attributes
form(Phoenix.HTML.Form) - Defaults tonil.field(:atom) - Defaults tonil.name(:string) - Explicit hidden-input name. Overrides form+field. Used byunit_input/1to inject a nested name likeheight[unit]. Defaults tonil.input_id(:string) - Explicit id for the hidden value input. Defaults tonil.current(:string) (required)category(:string) (required)locale(:any) - Defaults tonil.include_prefixed(:boolean) - Defaults tofalse.variant(:atom) - Defaults to:auto. Must be one of:auto,:dropdown, or:sheet.id(:string) - Defaults tonil.class(:string) - Defaults tonil.button_class(:string) - Defaults tonil.overlay_class(:string) - Defaults tonil.row_class(:string) - Defaults tonil.