Renders a form field including input, label, errors, and description.
A Phoenix.HTML.FormField
may be passed as argument,
which is used to retrieve the input name, id, and values.
Otherwise all attributes may be passed explicitly.
In addition to all HTML input types, the following type values are also supported:
"select"
"checkbox-group"
"radio-group"
"switch"
Note that the class
attribute is applied to the outer container, while
the rest
global attribute is applied to the <input>
element.
To translate field errors using Gettext, set the gettext_module
option
when building the component:
build_field(gettext_module: MyApp.Gettext)
The component does not provide an attribute to modify label positioning directly. Instead, label positioning should be handled with CSS. If your application requires different label positions, such as horizontal and vertical layouts, it is recommended to add a modifier class to the form.
For example, the default style could position labels above inputs. To place
labels to the left of the inputs in a horizontal form layout, you can add an
is-horizontal
class to the form:
<.form class="is-horizontal">
<!-- inputs -->
</.form>
Then, in your CSS, apply the necessary styles to the .field
class within
forms having the is-horizontal
class:
form.is-horizontal .field {
// styles to position label left of the input
}
The component has a hide_label
attribute to visually hide labels while still
making them accessible to screen readers. If all labels within a form need to
be visually hidden, it may be more convenient to define a
.has-visually-hidden-labels
modifier class for the <form>
.
<.form class="has-visually-hidden-labels">
<!-- inputs -->
</.form>
Ensure to take checkbox and radio labels into consideration when writing the CSS styles.
<.field field={@form[:name]} />
<.field field={@form[:email]} type="email" />
The radio-group
and checkbox-group
types allow you to easily render groups
of radio buttons or checkboxes with a single component invocation. The
options
attribute is required for these types and has the same format as
the options for the select
type, except that options may not be nested.
<.field
field={@form[:email]}
type="checkbox-group"
label="Cuisine"
options={[
{"Mexican", "mexican"},
{"Japanese", "japanese"},
{"Libanese", "libanese"}
]}
/>
Note that the checkbox-group
type renders an additional hidden input with
an empty value before the checkboxes. This ensures that a value exists in case
all checkboxes are unchecked. Consequently, the resulting list value includes
an extra empty string. While Ecto.Changeset.cast/3
filters out empty strings
in array fields by default, you may need to handle the additional empty string
manual in other contexts.
<Phoenix.Component.form for={%{}} as={:story} :let={f}> <.field field={f[:field]} id="field-basic-inputs-text" label="Text" type="text" placeholder="Some text"/> <.field field={f[:field]} id="field-basic-inputs-email" label="E-mail" type="email" placeholder="email@example.com"/> <.field field={f[:field]} id="field-basic-inputs-password" label="Password" type="password" placeholder="12345678"/> <.field field={f[:field]} id="field-basic-inputs-number" label="Number" type="number" placeholder="250"/> <.field field={f[:field]} id="field-basic-inputs-search" label="Search" type="search" placeholder="Search term"/> <.field field={f[:field]} id="field-basic-inputs-tel" label="Phone number" type="tel" placeholder="+818012345678"/> <.field field={f[:field]} id="field-basic-inputs-url" label="URL" type="url" placeholder="https://www.msf.org"/> <.field field={f[:field]} id="field-basic-inputs-textarea" label="Textarea" type="textarea" rows="5" placeholder="Some text"/> <.field field={f[:field]} id="field-basic-inputs-range" label="Range" max="100" min="0" type="range" step="10"/> <.field field={f[:field]} id="field-basic-inputs-color" label="Color" type="color"/> <.field field={f[:field]} id="field-basic-inputs-date" label="Date" type="date"/> <.field field={f[:field]} id="field-basic-inputs-time" label="Time" type="time"/> <.field field={f[:field]} id="field-basic-inputs-datetime-local" label="Datetime local" type="datetime-local"/> <.field field={f[:field]} id="field-basic-inputs-week" label="Week" type="week"/> <.field field={f[:field]} id="field-basic-inputs-select" label="Select" type="select" options={["Option 1", "Option 2", "Option 3"]}/> <.field field={f[:field]} id="field-basic-inputs-multiple-select" label="Multiple select" type="select" options={["Option 1", "Option 2", "Option 3"]} multiple/> <.field field={f[:field]} id="field-basic-inputs-radio-group" label="Radio group" type="radio-group" options={["Option 1", "Option 2", "Option 3"]}/> <.field field={f[:field]} id="field-basic-inputs-checkbox" label="Checkbox" type="checkbox"/> <.field field={f[:field]} id="field-basic-inputs-switch" label="Switch" type="switch"/> <.field field={f[:field]} id="field-basic-inputs-checkbox-group" label="Checkbox group" type="checkbox-group" options={["Option 1", "Option 2", "Option 3"]}/> </Phoenix.Component.form>
<Phoenix.Component.form for={%{}} as={:story} :let={f}> <.field field={f[:field]} id="field-description-and-errors-only-values" label="Dog breed" type="text" options={["Labrador Retriever", "German Shepherd", "Golden Retriever", "Bulldog", "Beagle", "Poodle", "Rottweiler", "Yorkshire Terrier", "Boxer", "Dachshund"]} placeholder="Beagle"/> <.field field={f[:field]} id="field-description-and-errors-labels-and-values" label="Dog breed" type="text" options={[{"Labrador Retriever", "labrador_retriever"}, {"German Shepherd", "german_shepherd"}, {"Golden Retriever", "golden_retriever"}, {"Bulldog", "bulldog"}, {"Beagle", "beagle"}, {"Poodle", "poodle"}, {"Rottweiler", "rottweiler"}, {"Yorkshire Terrier", "yorkshire_terrier"}, {"Boxer", "boxer"}, {"Dachshund", "dachshund"}]} placeholder="Poodle"/> </Phoenix.Component.form>
<Phoenix.Component.form for={%{}} as={:story} :let={f}> <.field field={f[:field]} id="field-description-and-errors-description" label="With description" type="text" placeholder="Some text"> <:description>Tell us about yourself.</:description> </.field> <.field field={f[:field]} id="field-description-and-errors-errors" label="Text" type="text" errors={["too many characters", "too boring"]} placeholder="With errors"/> <.field field={f[:field]} id="field-description-and-errors-description-and-errors" label="With description and errors" type="text" errors={["too many characters"]} placeholder="Some text"> <:addon_left>Tell us about yourself.</:addon_left> </.field> </Phoenix.Component.form>
<Phoenix.Component.form for={%{}} as={:story} :let={f}> <.field field={f[:field]} id="field-addons-addon-left" label="Left" type="text" placeholder="Some text"> <:addon_left> <.icon><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mail" > <rect width="20" height="16" x="2" y="4" rx="2" /><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" /> </svg> </.icon> </:addon_left> </.field> <.field field={f[:field]} id="field-addons-addon-right" label="Right" type="text" placeholder="Some text"> <:addon_right> <.icon><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mail" > <rect width="20" height="16" x="2" y="4" rx="2" /><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" /> </svg> </.icon> </:addon_right> </.field> <.field field={f[:field]} id="field-addons-addon-left-and-right" label="Left and right" type="text" placeholder="Some text"> <:addon_left> <.icon><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mail" > <rect width="20" height="16" x="2" y="4" rx="2" /><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" /> </svg> </.icon> </:addon_left> <:addon_right> <.icon><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check" > <path d="M20 6 9 17l-5-5" /> </svg> </.icon> </:addon_right> </.field> </Phoenix.Component.form>