Phoenix.HTML.Form

Helpers related to producing HTML forms.

The functions in this module can be used in three distinct scenario:

We will explore all three scenarios below.

With model data

The entry point for defining forms in Phoenix is with the form_for/4 function. For this example, we will use Ecto.Changeset, which integrate nicely with Phoenix forms via the phoenix_ecto package.

Imagine you have the following action in your controller:

def new(conn, _params) do
  changeset = User.changeset(%User{})
  render conn, "new.html", changeset: changeset
end

where User.changeset/2 is defined as follows:

def changeset(user, params \\ :empty) do
  cast(user, params)
end

Now a @changeset assign is available in views which we can pass to the form:

<%= form_for @changeset, user_path(@conn, :create), fn f -> %>
  <label>
    Name: <%= text_input f, :name %>
  </label>

  <label>
    Age: <%= select f, :age, 18..100 %>
  </label>

  <%= submit "Submit" %>
<% end %>

form_for/4 receives the Ecto.Changeset and converts it to a form, which is passed to the function as the argument f. All the remaining functions in this module receive the form and automatically generate the input fields, often by extracting information from the given changeset. For example, if the user had a default value for age set, it will automatically show up as selected in the form.

With connection data

form_for/4 expects as first argument any data structure that implements the Phoenix.HTML.FormData protocol. By default, Phoenix implements this protocol for Plug.Conn, allowing us to create forms based only on connection information.

This is useful when you are creating forms that are not backed by any kind of model data, like a search form.

<%= form_for @conn, search_path(@conn, :new), [name: :search], fn f -> %>
  <%= text_input f, :for %>
  <%= submit "Search" %>
<% end %>

Without form data

Sometimes we may want to generate a text_input/3 or any other tag outside of a form. The functions in this module also support such usage by simply passing an atom as first argument instead of the form.

<%= text_input :user, :name, value: "This is a prepopulated value" %>

Nested inputs

If your model layer supports embedding or nested associations, you can use inputs_for to attach nested data to the form.

Imagine the models:

defmodule User do
  use Ecto.Model

  schema "users" do
    field :name
    embeds_one :permalink, Permalink
  end
end

defmodule Permalink do
  use Ecto.Model

  embedded_schema do
    field :url
  end
end

In the form, you now can:

<%= form_for @changeset, user_path(@conn, :create), fn f -> %>
  <%= text_input f, :name %>

  <%= inputs_for f, :permalink, fn fp -> %>
    <%= text_input f, :url %>
  <% end %>
<% end %>

The default option can be given to populate the fields if none is given:

<%= inputs_for f, :permalink, [default: %Permalink{title: "default"}], fn fp -> %>
  <%= text_input f, :url %>
<% end %>

inputs_for/4 can be used to work with single entities or collections. When working with collections, :prepend and :append can be used to add entries to the collection stored in the changeset.

Source

Summary

__struct__()

Defines the Phoenix.HTML.Form struct

checkbox(form, field, opts \\ [])

Generates a checkbox

date_select(form, field, opts \\ [])

Generates select tags for date

datetime_select(form, field, opts \\ [])

Generates select tags for datetime

email_input(form, field, opts \\ [])

Generates an email input

file_input(form, field, opts \\ [])

Generates a file input

form_for(form_data, action, options \\ [], fun)

Generates a form tag with a form builder

hidden_input(form, field, opts \\ [])

Generates a hidden input

humanize(atom)

Converts an attribute/form field into its humanize version

input_type(form, field, mapping \\ %{"email" => :email_input, "password" => :password_input, "search" => :search_input, "url" => :url_input})

Gets the input type for a given field

input_validations(form, field)

Returns the HTML5 validations that would apply to the given field

inputs_for(form, field, options \\ [], fun)

Generate a new form builder for the given parameter in form

label(form, field)

Generates a label tag

label(form, field, text)

See label/2

label(form, field, text, opts)

See label/2

multiple_select(form, field, values, opts \\ [])

Generates a select tag with the given values

number_input(form, field, opts \\ [])

Generates a number input

password_input(form, field, opts \\ [])

Generates a password input

radio_button(form, field, value, opts \\ [])

Generates a radio button

range_input(form, field, opts \\ [])

Generates a range input

reset(value, opts \\ [])

Generates a reset input to reset all the form fields to their original state

search_input(form, field, opts \\ [])

Generates a search input

select(form, field, values, opts \\ [])

Generates a select tag with the given values

submit(value, opts \\ [])

Generates a submit input to send the form

telephone_input(form, field, opts \\ [])

Generates a telephone input

text_input(form, field, opts \\ [])

Generates a text input

textarea(form, field, opts \\ [])

Generates a textarea input

time_select(form, field, opts \\ [])

Generates select tags for time

url_input(form, field, opts \\ [])

Generates an url input

Types

t :: %Phoenix.HTML.Form{source: Phoenix.HTML.FormData.t, name: String.t, model: %{atom => term}, params: %{binary => term}, hidden: Keyword.t, options: Keyword.t, errors: Keyword.t, impl: module, id: String.t, index: nil | non_neg_integer}

Functions

__struct__()

Defines the Phoenix.HTML.Form struct.

Its fields are:

  • :source - the data structure given to form_for/4 that implements the form data protocol

  • :impl - the module with the form data protocol implementation. This is used to avoid multiple protocol dispatches.

  • :id - the id to be used when generating input fields

  • :name - the name to be used when generating input fields

  • :model - the model used to lookup field data

  • :params - the parameters associated to this form in case they were sent as part of a previous request

  • :hidden - a keyword list of fields that are required for submitting the form behind the scenes as hidden inputs

  • :options - a copy of the options given when creating the form via form_for/4 without any form data specific key

  • :errors - a keyword list of errors that associated with the form
Source
checkbox(form, field, opts \\ [])

Generates a checkbox.

This function is useful for sending boolean values to the server.

Examples

# Assuming form contains a User model
checkbox(form, :famous)
#=> <input name="user[famous]" type="hidden" value="false">
    <input checked="checked" id="user_famous" name="user[famous]"> type="checkbox" value="true")

Options

  • :checked_value - the value to be sent when the checkbox is checked. Defaults to “true”

  • :unchecked_value - the value to be sent then the checkbox is unchecked, Defaults to “false”

  • :value - the value used to check if a checkbox is checked or unchecked. The default value is extracted from the model if a model is available

All other options are forwarded to the underlying HTML tag.

Hidden fields

Because an unchecked checkbox is not sent to the server, Phoenix automatically generates a hidden field with the unchecked_value before the checkbox field to ensure the unchecked_value is sent when the checkbox is not marked.

Source
date_select(form, field, opts \\ [])

Generates select tags for date.

Check datetime_select/3 for more information on options and supported values.

Source
datetime_select(form, field, opts \\ [])

Generates select tags for datetime.

Examples

# Assuming form contains a User model
datetime_select form, :born_at
#=> <select id="user_born_at_year" name="user[born_at][year]">...</select> /
    <select id="user_born_at_month" name="user[born_at][month]">...</select> /
    <select id="user_born_at_day" name="user[born_at][day]">...</select> —
    <select id="user_born_at_hour" name="user[born_at][hour]">...</select> :
    <select id="user_born_at_min" name="user[born_at][min]">...</select>

If you want to include the seconds field (hidden by default), pass sec: []:

# Assuming form contains a User model
datetime_select form, :born_at, sec: []

If you want to configure the years range:

# Assuming form contains a User model
datetime_select form, :born_at, year: [options: 1900..2100]

You are also able to configure :month, :day, :hour, :min and :sec. All options given to those keys will be forwarded to the underlying select. See select/4 for more information.

Options

  • :value - the value used to select a given option. The default value is extracted from the model if a model is available

  • :default - the default value to use when none was given in :value and none was available in the model

  • :year, :month, :day, :hour, :min, :sec - options passed to the underlying select. See select/4 for more information. The available values can be given in :options.

  • :builder - specify how the select can be build. It must be a function that receives a builder that should be invoked with the select name and a set of options. See builder below for more information.

Builder

The generated datetime_select can be customized at will by providing a builder option. Here is an example from EEx:

<%= datetime_select form, :born_at, builder: fn b -> %>
  Date: <%= b.(:day, []) %> / <%= b.(:month, []) %> / <%= b.(:hour, []) %>
  Time: <%= b.(:hour, []) %> : <%= b.(:min, []) %>
<% end %>

Although we have passed empty lists as options (they are required), you could pass any option there and it would be given to the underlying select input.

In practice, we recommend you to create your own helper with your default builder:

def my_datetime_select(form, field, opts \\ []) do
  builder = fn b ->
    ~e"\""
    Date: <%= b.(:day, []) %> / <%= b.(:month, []) %> / <%= b.(:hour, []) %>
    Time: <%= b.(:hour, []) %> : <%= b.(:min, []) %>
    "\""
  end

  datetime_select(form, field, [builder: builder] ++ opts)
end

Then you are able to use your own datetime_select throughout your whole application.

Supported date values

The following values are supported as date:

  • a map containing the year, month and day keys (either as strings or atoms)
  • a tuple with three elements: {year, month, day}
  • nil

Supported time values

The following values are supported as time:

  • a map containing the hour and min keys and an optional sec key (either as strings or atoms)
  • a tuple with three elements: {hour, min, sec}
  • a tuple with four elements: {hour, min, sec, usec}
  • nil
Source
email_input(form, field, opts \\ [])

Generates an email input.

See text_input/3 for example and docs.

Source
file_input(form, field, opts \\ [])

Generates a file input.

It requires the given form to be configured with multipart: true when invoking form_for/4, otherwise it fails with ArgumentError.

See text_input/3 for example and docs.

Source
form_for(form_data, action, options \\ [], fun)

Specs:

Generates a form tag with a form builder.

See the module documentation for examples of using this function.

Options

  • :name - the name to be used in the form. May be inflected if a model is available

  • :method - the HTTP method. If the method is not “get” nor “post”, an input tag with name _method is generated along-side the form tag. Defaults to “post”.

  • :multipart - when true, sets enctype to “multipart/form-data”. Required when uploading files

  • :csrf_token - for “post” requests, the form tag will automatically include an input tag with name _csrf_token. When set to false, this is disabled

  • :enforce_utf8 - when false, does not enforce utf8

See Phoenix.HTML.Tag.form_tag/2 for more information on the options above.

Source
hidden_input(form, field, opts \\ [])

Generates a hidden input.

See text_input/3 for example and docs.

Source
humanize(atom)

Converts an attribute/form field into its humanize version.

iex> humanize(:username)
"Username"
iex> humanize(:created_at)
"Created at"
iex> humanize("user_id")
"User"
Source
input_type(form, field, mapping \\ %{"email" => :email_input, "password" => :password_input, "search" => :search_input, "url" => :url_input})

Gets the input type for a given field.

If the underlying input type is a :text_field, a mapping could be given to further inflect the input type based solely on the field name. The default mapping is:

%{"url"      => :url_input,
  "email"    => :email_input,
  "search"   => :search_input,
  "password" => :password_input}
Source
input_validations(form, field)

Specs:

  • input_validations(t, atom) :: boolean

Returns the HTML5 validations that would apply to the given field.

Source
inputs_for(form, field, options \\ [], fun)

Specs:

Generate a new form builder for the given parameter in form.

See the module documentation for examples of using this function.

Options

  • :id - the id to be used in the form, defaults to the concatenation of the given field to the parent form id

  • :name - the name to be used in the form, defaults to the concatenation of the given field to the parent form name

  • :default - the value to use if none is available

  • :prepend - the values to prepend when rendering. This only applies if the field value is a list and no parameters were sent through the form.

  • :append - the values to append when rendering. This only applies if the field value is a list and no parameters were sent through the form.
Source
label(form, field)

Generates a label tag.

The form should either be a Phoenix.HTML.Form emitted by form_for or an atom.

All given options are forwarded to the underlying tag. A default value is provided for for attribute but can be overriden if you pass a value to the for option. Text content would be inferred from field if not specified.

Examples

# Assuming form contains a User model
label(form, :name, "Name")
#=> <label for="user_name">Name</label>

label(:user, :email, "Email")
#=> <label for="user_email">Email</label>

label(:user, :email)
#=> <label for="user_email">Email</label>

label(:user, :email, class: "control-label")
#=> <label for="user_email" class="control-label">Email</label>
Source
label(form, field, text)

See label/2.

Source
label(form, field, text, opts)

See label/2.

Source
multiple_select(form, field, values, opts \\ [])

Generates a select tag with the given values.

Values are expected to be an Enumerable containing two-item tuples (like maps and keyword lists) or any Enumerable where the element will be used both as key and value for the generated select.

Examples

# Assuming form contains a User model
multiple_select(form, :roles, ["Admin": 1, "Power User": 2])
#=> <select id="user_roles" name="user[roles][]">
    <option value="1">Admin</option>
    <option value="2">Power User</option>
    </select>


multiple_select(form, :role, ["Admin": 1, "Power User": 2], values: [1])
#=> <select id="user_role" name="user[role]">
    <option value="1" selected="selected" >Admin</option>
    <option value="2">Power User</option>
    </select>

Options

  • :value - an Enum of values used to select given options.

  • :default - the default value to use when none was given in :values and none was available in the model

All other options are forwarded to the underlying HTML tag.

Source
number_input(form, field, opts \\ [])

Generates a number input.

See text_input/3 for example and docs.

Source
password_input(form, field, opts \\ [])

Generates a password input.

See text_input/3 for example and docs.

Source
radio_button(form, field, value, opts \\ [])

Generates a radio button.

Invoke this function for each possible value you to be sent to the server.

Examples

# Assuming form contains a User model
radio_button(form, :role, "admin")
#=> <input id="user_role_admin" name="user[role]" type="radio" value="admin">

Options

All options are simply forwarded to the underlying HTML tag.

Source
range_input(form, field, opts \\ [])

Generates a range input.

See text_input/3 for example and docs.

Source
reset(value, opts \\ [])

Generates a reset input to reset all the form fields to their original state.

All options are forwarded to the underlying input tag.

Examples

reset "Reset"
#=> <input type="reset" value="Reset">

reset "Reset", class: "btn"
#=> <input type="reset" value="Reset" class="btn">
Source
search_input(form, field, opts \\ [])

Generates a search input.

See text_input/3 for example and docs.

Source
select(form, field, values, opts \\ [])

Generates a select tag with the given values.

Values are expected to be an Enumerable containing two-item tuples (like maps and keyword lists) or any Enumerable where the element will be used both as key and value for the generated select.

Examples

# Assuming form contains a User model
select(form, :age, 0..120)
#=> <select id="user_age" name="user[age]">
    <option value="0">0</option>
    ...
    <option value="120">120</option>
    </select>

select(form, :role, ["Admin": "admin", "User": "user"])
#=> <select id="user_role" name="user[role]">
    <option value="admin">Admin</option>
    <option value="user">User</option>
    </select>

select(form, :role, ["Admin": "admin", "User": "user"], prompt: "Choose your role")
#=> <select id="user_role" name="user[role]">
    <option value="">Choose your role</option>
    <option value="admin">Admin</option>
    <option value="user">User</option>
    </select>

Options

  • :prompt - an option to include at the top of the options with the given prompt text

  • :value - the value used to select a given option. The default value is extracted from the model if a model is available

  • :default - the default value to use when none was given in :value and none was available in the model

All other options are forwarded to the underlying HTML tag.

Source
submit(value, opts \\ [])

Generates a submit input to send the form.

All options are forwarded to the underlying input tag.

Examples

submit "Submit"
#=> <input type="submit" value="Submit">
Source
telephone_input(form, field, opts \\ [])

Generates a telephone input.

See text_input/3 for example and docs.

Source
text_input(form, field, opts \\ [])

Generates a text input.

The form should either be a Phoenix.HTML.Form emitted by form_for or an atom.

All given options are forwarded to the underlying input, default values are provided for id, name and value if possible.

Examples

# Assuming form contains a User model
text_input(form, :name)
#=> <input id="user_name" name="user[name]" type="text" value="">

text_input(:user, :name)
#=> <input id="user_name" name="user[name]" type="text" value="">
Source
textarea(form, field, opts \\ [])

Generates a textarea input.

All given options are forwarded to the underlying input, default values are provided for id, name and textarea content if possible.

Examples

# Assuming form contains a User model
textarea(form, :description)
#=> <textarea id="user_description" name="user[description]"></textarea>

New lines

Notice the generated textarea includes a new line after the opening tag. This is because the HTML spec says new lines after tags must be ignored and all major browser implementations do that.

So in order to avoid new lines provided by the user from being ignored when the form is resubmitted, we automatically add a new line before the text area value.

Source
time_select(form, field, opts \\ [])

Generates select tags for time.

Check datetime_select/3 for more information on options and supported values.

Source
url_input(form, field, opts \\ [])

Generates an url input.

See text_input/3 for example and docs.

Source