Components Forms (v2)

Forms (v2)

v1.1.0+
These components use the new `to_form/2` functionality

In Phoenix 1.7, forms were given a new data structure. For more information see the release notes or the latest form docs.

v1 way (pre Phoenix 1.7):

# In your LiveView
def mount(_params, _session, socket) do
  changeset = Blog.changeset(%Post{})
  socket = assign(socket, changeset: changeset)
  {:ok, socket}
end
<.form :let={f} as={:user} for={@changeset} phx-submit="on_submit">
  <.form_field type="text_input" form={f} field={:title} />

  <.form_field
    form={f}
    field={:state}
    type="select"
    options={[{"Draft", "draft"}, {"Published", "published"}]}
  />

  <.button type="submit" label="Submit" />
</.form>

v2 way (Phoenix 1.7):

# In your LiveView
def mount(_params, _session, socket) do
  changeset = Blog.changeset(%Post{})
  socket = assign(socket, form: to_form(changeset))
  {:ok, socket}
end
<.form for={@form} phx-submit="on_submit">
  <.field field={@form[:title]} />

  <.field
    field={@form[:state]}
    type="select"
    options={[{"Draft", "draft"}, {"Published", "published"}]}
  />

  <.button type="submit" label="Submit" />
</.form>

Go here for the v1 docs. There is no rush to upgrade to v2. It only matters if you’d like to utilize the Live View optimizations around forms (see the links above for more information).

All fields example

Here’s an example of all the fields in one form. This is handy as a quick reference.

Field

`.field` is the easiest way to create input fields. We support all HTML input types plus a couple more.

not a pudding!

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

  <!-- Without a field  -->
  <.field label="Favourite pudding" value="mcdonalds" name="favourite_pudding" errors={["not a pudding!"]} />

  <.field type="password" field={@form[:password]} />
  <.field
    type="radio-group"
    options={[Male: "male", Female: "female", Other: "other"]}
    field={@form[:gender]}
  />
  <div class="flex justify-end gap-3">
    <.button type="button" label="Cancel" color="white" />
    <.button type="submit" label="Submit" />
  </div>
</.form>

        

Field properties

          attr :id, :any,
  default: nil,
  doc: "the id of the input. If not passed, it will be generated automatically from the field"

attr :name, :any,
  doc: "the name of the input. If not passed, it will be generated automatically from the field"

attr :label, :string,
  doc:
    "the label for the input. If not passed, it will be generated automatically from the field"

attr :value, :any,
  doc:
    "the value of the input. If not passed, it will be generated automatically from the field"

attr :type, :string,
  default: "text",
  values:
    ~w(checkbox checkbox-group color date datetime-local email file hidden month number password
            range radio-group search select switch tel text textarea time url week),
  doc: "the type of input"

attr :field, Phoenix.HTML.FormField,
  doc: "a form field struct retrieved from the form, for example: @form[:email]"

attr :errors, :list,
  default: [],
  doc:
    "a list of errors to display. If not passed, it will be generated automatically from the field. Format is a list of strings."

attr :checked, :any, doc: "the checked flag for checkboxes and checkbox groups"
attr :prompt, :string, default: nil, doc: "the prompt for select inputs"
attr :options, :list, doc: "the options to pass to Phoenix.HTML.Form.options_for_select/2"
attr :multiple, :boolean, default: false, doc: "the multiple flag for select inputs"
attr :disabled_options, :list, default: [], doc: "the options to disable in a checkbox group"

attr :group_layout, :string,
  values: ["row", "col"],
  default: "row",
  doc: "the layout of the inputs in a group (checkbox-group or radio-group)"

attr :empty_message, :string,
  default: nil,
  doc:
    "the message to display when there are no options available, for checkbox-group or radio-group"

attr :rows, :string, default: "4", doc: "rows for textarea"

attr :class, :string, default: nil, doc: "the class to add to the input"
attr :wrapper_class, :string, default: nil, doc: "the wrapper div classes"
attr :help_text, :string, default: nil, doc: "context/help for your field"
attr :label_class, :string, default: nil, doc: "extra CSS for your label"
attr :selected, :any, default: nil, doc: "the selected value for select inputs"

attr :required, :boolean,
  default: false,
  doc: "is this field required? is passed to the input and adds an asterisk next to the label"

attr :rest, :global,
  include:
    ~w(autocomplete disabled form max maxlength min minlength list
  pattern placeholder readonly required size step value name multiple prompt default year month day hour minute second builder options layout cols rows wrap checked accept),
  doc: "All other props go on the input"

        

Checkbox

Here is some help text
          <.field field={@form[:field_name]} type="checkbox" />

<-- With help text -->
<.field field={@form[:field_name]} type="checkbox" help_text="Here is some help text" />

<-- Just in the input -->
<.input field={@form[:field_name]} type="checkbox" />

        

See all field properties

Checkbox group

Here is some help text
The second option is disabled
          <.field
  field={@form[:field_name]}
  type="checkbox-group"
  options={[{"Option 1", "1"}, {"Option 2", "2"}, {"Option 3", "3"}]}
/>

<!-- With col layout -->
<.field
  field={@form[:field_name]}
  type="checkbox-group"
  options={[{"Option 1", "1"}, {"Option 2", "2"}, {"Option 3", "3"}]}
  group_layout="col"
/>

<!-- With help text -->
<.field
  field={@form[:field_name]}
  type="checkbox-group"
  options={[{"Option 1", "1"}, {"Option 2", "2"}, {"Option 3", "3"}]}
  help_text="Here is some help text"
/>

<!-- With disabled options -->
<.field
  field={@form[:field_name]}
  type="checkbox-group"
  options={[{"Option 1", "1"}, {"Option 2", "2"}, {"Option 3", "3"}]}
  help_text="The second option is disabled"
  disabled_options={["2"]}
/>

        

See all field properties

Color input

Here is some help text
          <.field field={@form[:field_name]} type="color" />

<!-- With help text -->
<.field field={@form[:field_name]} type="color" help_text="Here is some help text" />

<-- Just in the input -->
<.input field={@form[:field_name]} type="color" />

        

See all field properties

Date input

Here is some help text
          <.field field={@form[:field_name]} type="date" />

<!-- With help text -->
<.field field={@form[:field_name]} type="date" help_text="Here is some help text" />

<-- Just in the input -->
<.input field={@form[:field_name]} type="date" />

        

See all field properties

Datetime local input

Here is some help text
          <.field field={@form[:field_name]} type="datetime-local" />

<!-- With help text -->
<.field field={@form[:field_name]} type="datetime-local" help_text="Here is some help text" />

<-- Just in the input -->
<.input field={@form[:field_name]} type="datetime-local" />

        

See all field properties

Email input

Here is some help text
          <.field field={@form[:field_name]} type="email" />

<!-- With help text -->
<.field field={@form[:field_name]} type="email" help_text="Here is some help text" />

<-- Just in the input -->
<.input field={@form[:field_name]} type="email" />

        

See all field properties

File input

Here is some help text
          <.field field={@form[:field_name]} type="file" />

<!-- With help text -->
<.field field={@form[:field_name]} type="file" help_text="Here is some help text" />

<-- Just in the input -->
<.input field={@form[:field_name]} type="file" />

        

See all field properties

Hidden input

          <!-- This just renders the hidden input with no label -->
<.field field={@form[:field_name]} type="hidden" />

        

See all field properties

Number input

Here is some help text
          <.field field={@form[:field_name]} type="number" />

<!-- With help text -->
<.field field={@form[:field_name]} type="number" help_text="Here is some help text" />

<-- Just in the input -->
<.input field={@form[:field_name]} type="number" />

        

See all field properties

Password input

Here is some help text
          <.field field={@form[:field_name]} type="password" />

<!-- With help text -->
<.field field={@form[:field_name]} type="password" help_text="Here is some help text" />

<-- Just in the input -->
<.input field={@form[:field_name]} type="password" />

        

See all field properties

Radio group

Here is some help text
          <.field
  field={@form[:field_name]}
  type="radio-group"
  options={[{"Option 1", "1"}, {"Option 2", "2"}, {"Option 3", "3"}]}
/>

<!-- With a row layout -->
<.field
  field={@form[:field_name]}
  type="radio-group"
  options={[{"Option 1", "1"}, {"Option 2", "2"}, {"Option 3", "3"}]}
  group_layout="col"
/>

<!-- With help text -->
<.field
  field={@form[:field_name]}
  type="radio-group"
  options={[{"Option 1", "1"}, {"Option 2", "2"}, {"Option 3", "3"}]}
  help_text="Here is some help text"
/>

        

See all field properties

Range input

Here is some help text
          <.field field={@form[:field_name]} type="range" />

<!-- With help text -->
<.field field={@form[:field_name]} type="range" help_text="Here is some help text" />

<-- Just in the input -->
<.input field={@form[:field_name]} type="range" />

        

See all field properties

Here is some help text
          <.field field={@form[:field_name]} type="search" />

<!-- With help text -->
<.field field={@form[:field_name]} type="search" help_text="Here is some help text" />

<-- Just in the input -->
<.input field={@form[:field_name]} type="search" />

        

See all field properties

Select

Here is some help text
          <.field
  field={@form[:field_name]}
  type="select"
  options={[{"Option 1", "1"}, {"Option 2", "2"}, {"Option 3", "3"}]}
/>

<!-- With a prompt -->
<.field
  field={@form[:field_name]}
  type="select"
  options={[{"Option 1", "1"}, {"Option 2", "2"}, {"Option 3", "3"}]}
  prompt="Select an option"
/>

<!-- With help text -->
<.field
  field={@form[:field_name]}
  type="select"
  options={[{"Option 1", "1"}, {"Option 2", "2"}, {"Option 3", "3"}]}
  help_text="Here is some help text"
/>

<!-- With multiple -->
<.field
  field={@form[:field_name]}
  type="select"
  options={[{"Option 1", "1"}, {"Option 2", "2"}, {"Option 3", "3"}]}
  multiple={true}
/>

<!-- Just in the input -->
<.input
  field={@form[:field_name]}
  type="select"
  options={[{"Option 1", "1"}, {"Option 2", "2"}, {"Option 3", "3"}]}
/>

        

See all field properties

Switch

Here is some help text
          <.field field={@form[:field_name]} type="switch" />

<!-- With help text -->
<.field field={@form[:field_name]} type="switch" help_text="Here is some help text" />

<!-- Just in the input -->
<.input field={@form[:field_name]} type="switch" />

        

See all field properties

Telephone input

Here is some help text
          <.field field={@form[:field_name]} type="tel" />

<!-- With help text -->
<.field field={@form[:field_name]} type="tel" help_text="Here is some help text" />

<!-- Just in the input -->
<.input field={@form[:field_name]} type="tel" />

        

See all field properties

Text input

Here is some help text
          <.field field={@form[:field_name]} />

<!-- With a placeholder  -->
<.field field={@form[:field_name]} placeholder="eg. John" />

<!-- With help text -->
<.field field={@form[:field_name]} help_text="Here is some help text" />

<!-- Just the input  -->
<.input field={@form[:field_name]} placeholder="eg. John" />

        

See all field properties

Textarea

Here is some help text
          <.field field={@form[:field_name]} type="textarea" />

<!-- With help text -->
<.field field={@form[:field_name]} type="textarea" help_text="Here is some help text" />

<!-- Just the input  -->
<.input field={@form[:field_name]} type="textarea" />

        

See all field properties

Time input

Here is some help text
          <.field field={@form[:field_name]} type="time" />

<!-- With help text -->
<.field field={@form[:field_name]} type="time" help_text="Here is some help text" />

<!-- Just in the input -->
<.input field={@form[:field_name]} type="time" />

        

See all field properties

URL input

Here is some help text
          <.field field={@form[:field_name]} type="url" />

<!-- With help text -->
<.field field={@form[:field_name]} type="url" help_text="Here is some help text" />

<!-- Just in the input -->
<.input field={@form[:field_name]} type="url" />

        

Field label

          <.field_label>My label</.field_label>

        
          attr :for, :string, default: nil
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true

        

Field error

My Error

          <.field_error>My Error</.field_error>

        
          slot :inner_block, required: true

        

See all field properties