Fluxon.Components.Form
(Fluxon v3.1.2)
Provides <.label> and <.error>, the building blocks for labelling form controls and surfacing validation messages.
These two components handle the text that surrounds an input: the label that names a field (with room for a secondary note and a longer description) and the error message that reports a validation failure. They are intentionally small and composable so you can assemble custom field layouts, and they are the same primitives the higher-level inputs render internally.
Most of the time you never call these components directly. Fluxon.Components.Input and the other
form controls render <.label> and <.error> for you from their label, sublabel,
description, field, and errors attributes. Reach for <.label> and <.error> on their own
when you build a bespoke field arrangement that the standard input wrappers do not cover, or when
you want to place a label or an error somewhere the input component would not put it.
Relationship to the form inputs
<.input>, <.textarea>, <.select>, <.radio_group>, and <.checkbox_group> already call
these components. Pass label, sublabel, and description to those inputs to get a <.label>,
and let them translate field.errors into <.error> messages automatically. Use <.label> and
<.error> standalone only when you are composing a field layout by hand.
Usage
Label a control and describe the expectation with a sublabel and description:
<.label for="email" sublabel="Required" description="We'll never share your email.">
Email address
</.label>Report a validation failure below the control:
<.error>This field is required.</.error>Composed together into a hand-built field:
<div>
<.label for="username" sublabel="3-20 characters">Username</.label>
<input id="username" name="username" type="text" />
<.error>Username is already taken.</.error>
</div>Label anatomy
The label is a small grid with three optional pieces of text arranged for scannability:
| Part | Placement | Use Case |
|---|---|---|
Main text (inner_block) | The bold label | Names the field. Always present. |
sublabel | Inline, right of the main text, in a muted tone | Short qualifiers such as "Required", "Optional", or a character limit. |
description | On its own line below the label | A fuller sentence explaining the field or how the value is used. |
A label rendered immediately before a field element gains top spacing automatically, so stacked label-and-input pairs keep consistent vertical rhythm without extra classes.
Associating a label with its control
The for attribute wires the label to the control it names. Pass either a plain string id or a
Phoenix form field:
<!-- Plain id, matches the control's id attribute -->
<.label for="email">Email address</.label>
<input id="email" name="email" type="email" />
<!-- Phoenix form field: the label reads the field's id for you -->
<.label for={@form[:email]}>Email address</.label>When you pass a Phoenix.HTML.FormField, the component extracts field.id and uses it as the
for value, so the label points at the same element the matching input renders.
Error messages
<.error> renders a danger-colored message with a leading warning icon. It carries role="alert"
so the message is announced when it appears, which makes it suitable for validation output that
shows up after a form submission or a live change event.
Hide the icon when the message sits in a context that already communicates the error state, or when you want a plain-text treatment:
<.error icon={false}>Password must be at least 8 characters long.</.error>Give the error a stable id when a control needs to reference it (for example through
aria-describedby). The bundled form components set this id for you; you only need it when
wiring an error to a control by hand:
<input type="text" aria-describedby="username-error" />
<.error id="username-error">Username is already taken.</.error>Examples
A complete hand-composed field with a changeset-backed form:
<.form :let={f} for={@changeset} phx-submit="save" phx-change="validate">
<.label for={f[:email]} sublabel="Required" description="Used for sign-in and receipts.">
Email address
</.label>
<.input field={f[:email]} type="email" />
<.error :for={msg <- Enum.map(f[:email].errors, &translate_error/1)} id={"#{f[:email].id}-error"}>
{msg}
</.error>
</.form>A standalone error tied to a control through aria-describedby:
<label for="coupon">Coupon code</label>
<input id="coupon" name="coupon" type="text" aria-describedby="coupon-error" />
<.error id="coupon-error" icon={false}>That code has expired.</.error>A form-level summary error placed above the fields:
<.error :if={@form_error} class="mb-4">
{@form_error}
</.error>
Summary
Components
Renders a validation error message with an optional leading warning icon.
Renders a form label with an optional inline sublabel and a longer description.
Components
Renders a validation error message with an optional leading warning icon.
Use this to surface a validation failure for a form control. The message renders in the danger
color with a warning icon, and it carries role="alert" so it is announced when it appears, which
fits errors that show up after a submission or a live change event. It works both inside a form and
on its own, so you can also use it for form-level messages that are not tied to a single field.
The bundled form inputs already translate field.errors into <.error> messages for you; reach
for this component directly when you compose a field by hand or need an error somewhere the input
wrappers would not place one.
Attributes
id(:string) - Sets the id of the error element. Provide it when a control needs a stable target to reference, for example througharia-describedby. The bundled form components such asinput,textarea,radio_group, andcheckbox_groupset this automatically. Defaults tonil.Defaults to
nil.icon(:boolean) - Controls whether the leading warning icon is shown. Whentrue, a warning icon renders before the message. Set tofalsefor a plain-text error, or when the surrounding context already signals the error state. Defaults totrue.Defaults to
true.class(:any) - Sets additional CSS classes on the error container. Useful for adjusting spacing or layout, for example adding a top or bottom margin around a form-level message.Defaults to
nil.
Slots
inner_block(required) - The error message text describing the validation failure. Always rendered.
Examples
A basic field error:
<.error>This field is required.</.error>Without the icon, for a plainer treatment:
<.error icon={false}>
Password must be at least 8 characters long.
</.error>With an id so a control can reference it through aria-describedby:
<input type="text" aria-describedby="username-error" />
<.error id="username-error">Username is already taken.</.error>A form-level message spaced above the fields:
<.error class="mb-4">
Please fix the errors above before continuing.
</.error>
Renders a form label with an optional inline sublabel and a longer description.
Use this to name a form control in a custom field layout, when you are not relying on the
label, sublabel, and description attributes of the higher-level inputs. The main label text
comes from the slot, the sublabel sits inline beside it in a muted tone for short qualifiers, and
the description renders on its own line below for a fuller explanation.
Associate the label with its control through for, which accepts either a plain element id or a
Phoenix.HTML.FormField. When you pass a field, the component reads field.id so the label points
at the element the matching input renders. A label placed directly before a field element also
gains top spacing automatically, keeping stacked label-and-input pairs evenly spaced.
Attributes
for(:any) - Specifies the control this label names, rendered as theforattribute. Accepts a plain element id string or aPhoenix.HTML.FormField; when given a field, the label uses the field's id so it points at the same element the matching input renders. Defaults tonil.Defaults to
nil.class(:any) - Sets additional CSS classes on the<label>element. Useful for adjusting typography, color, or spacing of the main label text beyond the defaults.Defaults to
nil.description(:string) - Provides a longer explanatory sentence rendered on its own line below the label. Use it to clarify what the field is for or how the value will be used. Defaults tonil(no description).Defaults to
nil.sublabel(:string) - Sets a short supplementary note displayed inline to the right of the main label in a muted tone. Best suited for brief qualifiers such as "Required", "Optional", or a character limit. Defaults tonil(no sublabel).Defaults to
nil.Global attributes are accepted. Additional HTML attributes passed through to the
<label>element, such asdata-*hooks or event bindings.
Slots
inner_block(required) - The main label text that names the field. This is the primary, bold text of the label and is always rendered.
Examples
Label with a sublabel and description:
<.label for="email" sublabel="Required" description="We'll never share your email.">
Email address
</.label>Bound to a Phoenix form field, so the for id is derived from the field:
<.form :let={f} for={@changeset} phx-submit="save">
<.label for={f[:email]} sublabel="We'll never share your email.">
Email address
</.label>
<.input field={f[:email]} type="email" />
</.form>