Field

Renders a form field including input, label, errors, and description.

Read more Read less

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.

Maturity: Developing

Usage

Custom types

You can register additional input types at build time with the types option.

build_field(
  types: %{"ranked" => &MyAppWeb.Inputs.ranked/1}
)

The additional types can be rendered like any other types.

<.field field={@form[:rank]} type="ranked" label="Rank" />

The map is merged into the built-in types. You can set an entry to nil to remove a built-in type you do not use, and to :default to keep the built-in control, for example after a shared configuration replaced it.

build_field(
  types: %{
    "select" => &MyAppWeb.Inputs.select/1,
    "color" => nil,
    "week" => nil
  }
)

Types that render a group

Sometimes a control needs to render multiple inputs, for example a date field with separate selects for each segment. Set group: true on such types, so that the controls are wrapped inside a fieldset with a legend.

build_field(
  types: %{
    "permissions" => {&MyAppWeb.Inputs.permissions/1, group: true}
  }
)

The fieldset has the class #{base_class}-#{type}. Errors and description are rendered outside of the fieldset.

The options assign can be used to pass additional options to your custom type. The only requirement is that it is a list.

The field component renders the label, the errors and the description as it does for any other type, and calls your function component for the control. Your component receives these assigns:

| Assign | | |---|---| | name | the input name, with [] appended when multiple is set | | id | the id attribute, from id or the form field | | value | the field value | | type | the type you registered | | options | the options the caller passed, or nil | | prompt | the prompt the caller passed, or nil | | multiple | whether the field takes more than one value | | invalid | whether the field has errors, for aria-invalid | | describedby | for aria-describedby, nil without a description | | errormessage | for aria-errormessage, nil without errors | | validations | the validation attributes derived from the changeset | | rest | the global attributes the caller passed |

The component you referenced renders the control:

attr :name, :string, required: true
attr :id, :string, required: true
attr :value, :any, required: true
attr :type, :string, required: true
attr :options, :list, required: true
attr :prompt, :string, required: true
attr :multiple, :boolean, required: true
attr :invalid, :boolean, required: true
attr :describedby, :string, required: true
attr :errormessage, :string, required: true
attr :validations, :list, required: true
attr :rest, :global, doc: "Any additional HTML attributes."

def ranked(assigns) do
  ~H"""
  <div class="ranked" data-type={@type}>
    <select
      name={@name}
      id={@id}
      aria-describedby={@describedby}
      aria-errormessage={@errormessage}
      aria-invalid={@invalid && "true"}
      {@validations}
      {@rest}
    >
      <option
        :for={n <- 1..5}
        value={n}
        selected={to_string(n) == to_string(@value)}
      >
        {n}
      </option>
    </select>
  </div>
  """
end

Types

In addition to all HTML input types, the following type values are also supported:

  • "select"
  • "checkbox-group"
  • "radio-group"
  • "switch"

Class and Global Attribute

Note that the class attribute is applied to the outer container, while the rest global attribute is applied to the <input> element.

Gettext

To translate field errors as well as the required_text and optional_text using Gettext, set the gettext_module option when building the component:

build_field(gettext_module: MyApp.Gettext)

Label positioning

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.

Examples

<.field field={@form[:name]} />
<.field field={@form[:email]} type="email" />

Radio group and checkbox group

The radio-group and checkbox-group 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.

Keyboard

  • Space - toggle a checkbox or a switch.
  • Left, Right, Up and Down - move between the radios of a group and check the one the focus lands on.

The controls are native elements, so the browser handles these.

Attribute Type Documentation Default Value
checked :boolean

The checked attribute for checkboxes.

checked_value :string

The value that is sent when the checkbox is checked.

"true"
class :any

Any additional classes to be added.

Read more Read less
[]

Variations of the component should be expressed via modifier attributes, and it is preferable to use styles on the parent container to arrange components on the page, but if you have to, you can use this attribute to pass additional utility classes to the component.

The value can be a string or a list of strings.

errors :list
field %FormField{}

A form field struct, for example: @form[:name]

gettext :atom

The Gettext module to use for translating error messages. This option

Read more Read less

can also be set globally, see above.

hidden_input :boolean

If true, a hidden input with a false value is rendered before each

Read more Read less
true

checkbox, so that the form payload always has a parameter for that field.

hide_label :boolean

Adds a data-visually-hidden attribute to the <label>. This option

Read more Read less
false

does not apply to checkbox and radio inputs.

This requires a CSS rule for the data-visually-hidden attribute. See Visually hidden text.

id :any
label :string

Required for all types except "hidden".

Read more Read less
multiple :boolean

Sets the multiple attribute on a select element to allow selecting

Read more Read less
false

multiple options, or on a file input to allow selecting multiple files.

name :any
off_text :string

The state text for a switch when off. This value should be translated to

Read more Read less
"Off"

the language in which the rest of the page is displayed.

on_text :string

The state text for a switch when on. This value should be translated to

Read more Read less
"On"

the language in which the rest of the page is displayed.

options :list

A list of options.

Read more Read less

This attribute is supported for the following types:

  • "select"
  • "radio-group"
  • "checkbox-group"
  • other text types, date and time types, and the "range" type

If this attribute is set for types other than select, radio, and checkbox, a datalist is rendered for the input.

See Phoenix.HTML.Form.options_for_select/2 for the format.

Nested options group the choices. A select renders an optgroup, and a checkbox or radio group a nested fieldset with the group's name as its legend.

options={[{"Cool", [{"Blue", "blue"}]}, {"Warm", [{"Red", "red"}]}]}

Options can also be written as a keyword list with these keys:

  • :key (required)
  • :value (required)
  • :description (optional)

Any additional keys are passed as attributes to the control.

The description is rendered after the control and its label. It is only supported for checkbox and radio groups.

options={[[key: "Blue", value: "blue", description: "Sky"]]}
prompt :string

An optional prompt for select elements.

rest :global

Any additional HTML attributes.

type :string "text"
validations :list

A list of HTML input validation attributes (required, minlength,

Read more Read less

maxlength, min, max, pattern). The attributes are derived automatically from the form.

value :any
addon_left :slot

Can be used to render an icon left in the input. Only supported for single-line inputs.

[Multiple values]
addon_right :slot

Can be used to render an icon left in the input. Only supported for single-line inputs.

[Multiple values]
description :slot

A field description to render underneath the input.