Phoenix.HTML v2.9.1 Phoenix.HTML.Form
Helpers related to producing HTML forms.
The functions in this module can be used in three distinct scenarios:
with changeset data - when information to populate the form comes from a changeset
with connection data - when a form is created based on the information in the connection (aka
Plug.Conn
)without form data - when the functions are used directly, outside of a form
We will explore all three scenarios below.
With changeset 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 \\ %{}) do
cast(user, params, [:name, :age])
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 data from the data layer, like a search form.
<%= form_for @conn, search_path(@conn, :new), [as: :search], fn f -> %>
<%= text_input f, :for %>
<%= submit "Search" %>
<% end %>
form_for/4
uses the Plug.Conn
to set input values from the
request parameters. In this case, the input’s value would be set
to @conn.params["search"]["for"]
.
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 data layer supports embedding or nested associations,
you can use inputs_for
to attach nested data to the form.
Imagine the following Ecto schemas:
defmodule User do
use Ecto.Schema
schema "users" do
field :name
embeds_one :permalink, Permalink
end
end
defmodule Permalink do
use Ecto.Schema
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 fp, :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 fp, :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.
Summary
Functions
Defines the Phoenix.HTML.Form struct
Generates a checkbox
Generates a color input
Generates select tags for date
Generates select tags for datetime
Generates an email input
Generates a file input
Generates a form tag with a form builder
Generates a hidden input
Converts an attribute/form field into its humanize version
Returns an id of a corresponding form field
Returns a name of a corresponding form field
Gets the input type for a given field
Returns the HTML5 validations that would apply to the given field
Returns a value of a corresponding form field
Generate a new form builder for the given parameter in form
Generates a label tag
Generates a select tag with the given options
Generates a number input
Generates a password input
Generates a radio button
Generates a range input
Generates a reset input to reset all the form fields to their original state
Generates a search input
Generates a select tag with the given options
Generates a submit button to send the form
Generates a telephone input
Generates a text input
Generates a textarea input
Generates select tags for time
Generates an url input
Types
Functions
Defines the Phoenix.HTML.Form struct.
Its fields are:
:source
- the data structure given toform_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:data
- the field used to store lookup 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 viaform_for/4
without any form data specific key:errors
- a keyword list of errors that associated with the form
Generates a checkbox.
This function is useful for sending boolean values to the server.
Examples
# Assuming form contains a User schema
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 form data if 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.
Generates a color input.
Warning: this feature isn’t available in all browsers.
Check http://caniuse.com/#feat=input-color
for further informations.
See text_input/3
for example and docs.
Generates select tags for date.
Check datetime_select/3
for more information on options and supported values.
Generates select tags for datetime.
Examples
# Assuming form contains a User schema
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][minute]">...</select>
If you want to include the seconds field (hidden by default), pass second: []
:
# Assuming form contains a User schema
datetime_select form, :born_at, second: []
If you want to configure the years range:
# Assuming form contains a User schema
datetime_select form, :born_at, year: [options: 1900..2100]
You are also able to configure :month
, :day
, :hour
, :minute
and
:second
. 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 form data if available:default
- the default value to use when none was given in:value
and none is available in the form data:year
,:month
,:day
,:hour
,:minute
,:second
- options passed to the underlying select. Seeselect/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.(:year, []) %>
Time: <%= b.(:hour, []) %> : <%= b.(:minute, []) %>
<% 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.(:year, []) %>
Time: <%= b.(:hour, []) %> : <%= b.(:minute, []) %>
"\""
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
andday
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
andmin
keys and an optionalsec
key (either as strings or atoms) - a tuple with three elements:
{hour, min, sec}
- a tuple with four elements:
{hour, min, sec, usec}
nil
Generates an email input.
See text_input/3
for example and docs.
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.
form_for(Phoenix.HTML.FormData.t, String.t, Keyword.t, (t -> Phoenix.HTML.unsafe)) :: Phoenix.HTML.safe
Generates a form tag with a form builder.
See the module documentation for examples of using this function.
Options
:as
- the server side parameter in which all params for this form will be collected (i.e.as: :user_params
would mean all fields for this form will be accessed asconn.params.user_params
server side). Automatically inflected when a changeset is given.: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
- the form will have anaccept-charset
attribute set to “UTF-8” and a hidden input named_utf8
containing a unicode character to force the browser to use UTF-8 as the charset. When set to false, this is disabled.
See Phoenix.HTML.Tag.form_tag/2
for more information on the
options above.
Converts an attribute/form field into its humanize version.
iex> humanize(:username)
"Username"
iex> humanize(:created_at)
"Created at"
iex> humanize("user_id")
"User"
Returns an id of a corresponding form field.
The form should either be a Phoenix.HTML.Form
emitted
by form_for
or an atom.
Returns a name of a corresponding form field.
The form should either be a Phoenix.HTML.Form
emitted
by form_for
or an atom.
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}
Returns the HTML5 validations that would apply to the given field.
Returns a value of a corresponding form field.
The form
should either be a Phoenix.HTML.Form
emitted
by form_for
or an atom.
When a form is given, the value will first be looked up in
params
, then fallback to the optional computed
argument.
If no computed
argument is provided, it will try to fetch
the value from the form data.
The computed
argumented has higher precedence over the
data
since it is an attribute computed from the data
.
For example:
input_value(form, :name, String.upcase(form.data.name))
Always returns computed
if the given form is an atom.
inputs_for(t, atom, Keyword.t, (t -> Phoenix.HTML.unsafe)) :: Phoenix.HTML.safe
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 givenfield
to the parent form id:as
- the name to be used in the form, defaults to the concatenation of the givenfield
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.
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 schema
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>
label :user, :email do
"E-mail Address"
end
#=> <label for="user_email">E-mail Address</label>
label :user, :email, class: "control-label" do
"E-mail Address"
end
#=> <label class="control-label" for="user_email">E-mail Address</label>
See label/2
.
See label/2
.
Generates a select tag with the given options
.
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 schema
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, :roles, ["Admin": 1, "Power User": 2], value: [1])
#=> <select id="user_roles" name="user[roles]">
<option value="1" selected="selected" >Admin</option>
<option value="2">Power User</option>
</select>
When working with structs, associations and embeds, you will need to tell
Phoenix how to extract the value out of the collection. For example,
imagine user.roles
is a list of %Role{}
structs. You must call it as:
multiple_select(form, :roles, ["Admin": 1, "Power User": 2],
selected: Enum.map(@user.roles, &(&1.id))
The :selected
option will mark the given IDs as selected unless the form
is being resubmitted. When resubmitted, it uses the form params as values.
Options
:value
- an Enum of values used to select given options.:selected
- the default value to use when none was given in:value
and none was sent as parameter
All other options are forwarded to the underlying HTML tag.
Generates a number input.
See text_input/3
for example and docs.
Generates a password input.
For security reasons, the form data and parameter values
are never re-used in password_input/3
. Pass the value
explicitly if you would like to set one.
See text_input/3
for example and docs.
Generates a radio button.
Invoke this function for each possible value you to be sent to the server.
Examples
# Assuming form contains a User schema
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.
Generates a range input.
See text_input/3
for example and docs.
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">
Generates a search input.
See text_input/3
for example and docs.
Generates a select tag with the given options
.
Values are expected to be an Enumerable containing two-item tuples (like a regular list or a map) or any Enumerable where the element will be used both as key and value for the generated select.
Optgroups
When a two-item map contains a list as its value,
the options will be wrapped in an <optroup>
using the key as its label.
Examples
# Assuming form contains a User schema
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>
select(form, :country, %{"Europe" => ["UK", "Sweden", "France"], …})
#=> <select id="user_country" name="user[country]">
<optgroup label="Europe">
<option>UK</option>
<option>Sweden</option>
<option>France</option>
</optgroup>
...
</select>
# Assuming users is a list of User schemas and form contains a Resource Schema
select(form, :user_id, users |> Enum.map(&{&1.name, &1.id}))
#=> <select id="user_id" name="resource[user_id]">
<option value="1">Ylva</option>
<option value="2">Annora</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 form data if available:selected
- the default value to use when none was given in:value
and none was sent as parameter
All other options are forwarded to the underlying HTML tag.
Generates a submit button to send the form.
All options are forwarded to the underlying button tag.
Examples
submit "Submit"
#=> <button type="submit">Submit</button>
Generates a telephone input.
See text_input/3
for example and docs.
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 schema
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="">
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 schema
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.
Generates select tags for time.
Check datetime_select/3
for more information on options and supported values.
Generates an url input.
See text_input/3
for example and docs.