View Source Phoenix.HTML.Form (Phoenix.HTML v3.3.3)

Define a Phoenix.HTML.Form struct and functions to interact with it.

For building actual forms in your Phoenix application, see the Phoenix.Component.form/1 component.

Access behaviour

The Phoenix.HTML.Form struct implements the Access behaviour. When you do form[field], it returns a Phoenix.HTML.FormField struct with the id, name, value, and errors prefilled.

The field name can be either an atom or a string. If it is an atom, it assumes the form keeps both data and errors as atoms. If it is a string, it considers that data and errors are stored as strings for said field. Forms backed by an Ecto.Changeset only support atom field names.

It is possible to "access" fields which do not exist in the source data structure. A Phoenix.HTML.FormField struct will be dynamically created with some attributes such as name and id populated.

Custom implementations

There is a protocol named Phoenix.HTML.FormData which can be implemented by any data structure that wants to be cast to the Phoenix.HTML.Form struct.

Summary

Functions

Defines the Phoenix.HTML.Form struct.

Generates a checkbox.

Generates a color input.

Generates a date input.

Generates select tags for date.

Generates a datetime-local input.

Generates select tags for datetime.

Generates an email input.

Generates a file input.

Generates a form tag with a form builder and an anonymous function.

Generates a hidden input.

Generates hidden inputs for the given form inputs.

Converts an attribute/form field into its humanize version.

Receives two forms structs and checks if the given field changed.

Returns an id of a corresponding form field.

Returns an id of a corresponding form field and value attached to it.

Returns a name of a corresponding form field.

Returns the HTML 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 label tag for the given field.

Generates a select tag with the given options.

Normalizes an input value according to its input type.

Generates a number input.

Returns options to be used inside a select.

Generates a password input.

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 submit button to send the form.

Generates a telephone input.

Generates a text input.

Generates a textarea input.

Generates a time input.

Generates select tags for time.

Generates an url input.

Types

@type field() :: atom() | String.t()
@type t() :: %Phoenix.HTML.Form{
  action: nil | String.t(),
  data: %{required(field()) => term()},
  errors: [{field(), term()}],
  hidden: Keyword.t(),
  id: String.t(),
  impl: module(),
  index: nil | non_neg_integer(),
  name: String.t(),
  options: Keyword.t(),
  params: %{required(binary()) => term()},
  source: Phoenix.HTML.FormData.t()
}

Functions

Link to this function

%Phoenix.HTML.Form{}

View Source (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

  • :index - the index of the struct in the form

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

  • :data - the field used to store lookup data

  • :params - the parameters associated with this form

  • :hidden - a keyword list of fields that are required to submit 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 are associated with the form

Link to this function

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

View Source

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"

  • :hidden_input - controls if this function will generate a hidden input to submit the unchecked value or not. Defaults to "true"

  • :unchecked_value - the value to be sent when 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. Set hidden_input to false If you don't want to send values from unchecked checkbox to the server.

Link to this function

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

View Source

Generates a color input.

See text_input/3 for example and docs.

Link to this function

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

View Source

Generates a date input.

See text_input/3 for example and docs.

Link to this function

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

View Source

Generates select tags for date.

Warning: This functionality is best provided by browsers nowadays. Consider using date_input/3 instead.

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

Link to this function

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

View Source

Generates a datetime-local input.

See text_input/3 for example and docs.

Link to this function

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

View Source

Generates select tags for datetime.

Warning: This functionality is best provided by browsers nowadays. Consider using datetime_local_input/3 instead.

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.

For example, if you are using Phoenix with Gettext and you want to localize the list of months, you can pass :options to the :month key:

# Assuming form contains a User schema
datetime_select form, :born_at, month: [
  options: [
    {gettext("January"), "1"},
    {gettext("February"), "2"},
    {gettext("March"), "3"},
    {gettext("April"), "4"},
    {gettext("May"), "5"},
    {gettext("June"), "6"},
    {gettext("July"), "7"},
    {gettext("August"), "8"},
    {gettext("September"), "9"},
    {gettext("October"), "10"},
    {gettext("November"), "11"},
    {gettext("December"), "12"},
  ]
]

You may even provide your own localized_datetime_select/3 built on top of datetime_select/3:

defp localized_datetime_select(form, field, opts \\ []) do
  opts =
    Keyword.put(opts, :month, options: [
      {gettext("January"), "1"},
      {gettext("February"), "2"},
      {gettext("March"), "3"},
      {gettext("April"), "4"},
      {gettext("May"), "5"},
      {gettext("June"), "6"},
      {gettext("July"), "7"},
      {gettext("August"), "8"},
      {gettext("September"), "9"},
      {gettext("October"), "10"},
      {gettext("November"), "11"},
      {gettext("December"), "12"},
    ])

  datetime_select(form, field, opts)
end

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. 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.(: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 ->
    assigns = %{b: b}

    ~H"""
    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 and day keys (either as strings or atoms)
  • a tuple with three elements: {year, month, day}
  • a string in ISO 8601 format
  • nil

Supported time values

The following values are supported as time:

  • a map containing the hour and minute keys and an optional second key (either as strings or atoms)
  • a tuple with three elements: {hour, min, sec}
  • a tuple with four elements: {hour, min, sec, usec}
  • nil
Link to this function

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

View Source

Generates an email input.

See text_input/3 for example and docs.

Link to this function

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

View Source

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.

Link to this function

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

View Source

Generates a form tag with a form builder and an anonymous function.

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

Forms may be used in two distinct scenarios:

  • with changeset data - when information to populate the form comes from a changeset. The changeset holds rich information, which helps provide conveniences

  • with map data - a simple map of parameters (such as Plug.Conn.params can be given as data to the form)

We will explore all them below.

Note that if you are using HEEx templates, form_for/4 is no longer the preferred way to generate a form tag, and you should use Phoenix.Component.form/1 instead.

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 integrates 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
  Ecto.Changeset.cast(user, params, [:name, :age])
end

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

<%= form_for @changeset, Routes.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.

A note on :errors

Even if changeset.errors is non-empty, errors will not be displayed in a form if the changeset :action is nil or :ignore.

This is useful for things like validation hints on form fields, e.g. an empty changeset for a new form. That changeset isn't valid, but we don't want to show errors until an actual user action has been performed.

For example, if the user submits and a Repo.insert/1 is called and fails on changeset validation, the action will be set to :insert to show that an insert was attempted, and the presence of that action will cause errors to be displayed. The same is true for Repo.update/delete.

If you want to show errors manually you can also set the action yourself, either directly on the Ecto.Changeset struct field or by using Ecto.Changeset.apply_action/2. Since the action can be arbitrary, you can set it to :validate or anything else to avoid giving the impression that a database operation has actually been attempted.

With map data

form_for/4 expects as first argument any data structure that implements the Phoenix.HTML.FormData protocol. By default, Phoenix.HTML implements this protocol for Map.

This is useful when you are creating forms that are not backed by any kind of data layer. Let's assume that we're submitting a form to the :new action in the FooController:

<%= form_for @conn.params, Routes.foo_path(@conn, :new), fn f -> %>
  <%= text_input f, :contents %>
  <%= submit "Search" %>
<% end %>

Once the form is submitted, the form contents will be set directly as the parameters root, such as conn.params["contents"]. If you prefer, you can pass the :as option to configure them to be nested:

<%= form_for @conn.params["search"] || %{}, Routes.foo_path(@conn, :new), [as: :search], fn f -> %>
  <%= text_input f, :contents %>
  <%= submit "Search" %>
<% end %>

In the example above, all form contents are now set inside conn.params["search"] thanks to the [as: :search] option.

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

  def changeset(user \ %User{}, params) do
    user
    |> Ecto.Changeset.cast(params, [:name])
    |> Ecto.Changeset.cast_embed(:permalink)
  end
end

defmodule Permalink do
  use Ecto.Schema

  embedded_schema do
    field :url
  end
end

In the form, you can now do this:

<%= form_for @changeset, Routes.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.

CSRF protection

CSRF protection is a mechanism to ensure that the user who rendered the form is the one actually submitting it. This module generates a CSRF token by default. Your application should check this token on the server to prevent attackers from making requests on your server on behalf of other users. Phoenix checks this token by default.

When posting a form with a host in its address, such as "//host.com/path" instead of only "/path", Phoenix will include the host signature in the token, and will only validate the token if the accessed host is the same as the host in the token. This is to avoid tokens from leaking to third-party applications. If this behaviour is problematic, you can generate a non-host-specific token with Plug.CSRFProtection.get_csrf_token/0 and pass it to the form generator via the :csrf_token option.

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 as conn.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.

  • :errors - use this to manually pass a keyword list of errors to the form (for example from conn.assigns[:errors]). This option is only used when a connection is used as the form source and it will make the errors available under f.errors.

  • :id - the ID of the form attribute. If an ID is given, all form inputs will also be prefixed by the given ID.

All other options will be passed as HTML attributes, such as class: "foo".

Link to this function

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

View Source

Generates a hidden input.

See text_input/3 for example and docs.

@spec hidden_inputs_for(t()) :: [Phoenix.HTML.safe()]

Generates hidden inputs for the given form inputs.

See inputs_for/2 and inputs_for/3.

Converts an attribute/form field into its humanize version.

iex> humanize(:username)
"Username"
iex> humanize(:created_at)
"Created at"
iex> humanize("user_id")
"User"
Link to this function

input_changed?(form1, form2, field)

View Source
@spec input_changed?(t(), t(), field()) :: boolean()

Receives two forms structs and checks if the given field changed.

The field will have changed if either its associated value or errors changed. This is mostly used for optimization engines as an extension of the Access behaviour.

@spec input_id(t() | atom(), field()) :: String.t()

Returns an id of a corresponding form field.

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

Link to this function

input_id(name, field, value)

View Source
@spec input_id(t() | atom(), field(), Phoenix.HTML.Safe.t()) :: String.t()

Returns an id of a corresponding form field and value attached to it.

Useful for radio buttons and inputs like multiselect checkboxes.

Link to this function

input_name(form_or_name, field)

View Source
@spec input_name(t() | atom(), field()) :: String.t()

Returns a name of a corresponding form field.

The first argument should either be a Phoenix.HTML.Form or an atom.

Examples

iex> Phoenix.HTML.Form.input_name(:user, :first_name)
"user[first_name]"
Link to this function

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

View Source

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}
Link to this function

input_validations(form, field)

View Source
@spec input_validations(t(), field()) :: Keyword.t()

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

Link to this function

input_value(form, field)

View Source
@spec input_value(t() | atom(), field()) :: term()

Returns a value of a corresponding form field.

The form should either be a Phoenix.HTML.Form or an atom. The field is either a string or an atom. If the field is given as an atom, it will attempt to look data with atom keys. If a string, it will look data with string keys.

When a form is given, it will look for changes, then fallback to parameters, and finally fallback to the default struct/map value.

Since the function looks up parameter values too, there is no guarantee that the value will have a certain type. For example, a boolean field will be sent as "false" as a parameter, and this function will return it as is. If you need to normalize the result of input_value, see normalize_value/2.

Link to this function

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

View Source
@spec inputs_for(t(), field(), Keyword.t(), (t() -> Phoenix.HTML.unsafe())) ::
  Phoenix.HTML.safe()

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

See form_for/4 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

  • :as - 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.

  • :skip_hidden - skip the automatic rendering of hidden fields to allow for more tight control over the generated markup. You can access form.hidden to generate them manually within the supplied callback.

Generates a label tag.

Useful when wrapping another input inside a label.

Examples

label do
  radio_button :user, :choice, "Choice"
end
#=> <label>...</label>

label class: "control-label" do
  radio_button :user, :choice, "Choice"
end
#=> <label class="control-label">...</label>

Generates a label tag for the given field.

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 overridden if you pass a value to the for option. Text content would be inferred from field if not specified as either a function argument or string value in a block.

To wrap a label around an input, see label/1.

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, "E-mail Address", class: "control-label"
#=> <label class="control-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>
Link to this function

label(form, field, text_or_do_block_or_attributes)

View Source

See label/2.

Link to this function

label(form, field, text, do_block_or_attributes)

View Source

See label/2.

Link to this function

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

View Source

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], selected: [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.

When used with Ecto, you will typically do a query to retrieve the IDs from the database:

from r in Role, where: r.id in ^(params["roles"] || [])

And then use Ecto.Changeset.put_assoc/2 to insert the new roles into the user.

Options

  • :selected - the default options to be marked as selected. The values on this list are ignored in case ids have been set as parameters.

All other options are forwarded to the underlying HTML tag.

Link to this function

normalize_value(arg1, value)

View Source

Normalizes an input value according to its input type.

Certain HTML input values must be cast, or they will have idiosyncracies when they are rendered. The goal of this function is to encapsulate this logic. In particular:

  • For "datetime-local" types, it converts DateTime and NaiveDateTime to strings without the second precision

  • For "checkbox" types, it returns a boolean depending on whether the input is "true" or not

  • For "textarea", it prefixes a newline to ensure newlines won't be ignored on submission. This requires however that the textarea is rendered with no spaces after its content

Link to this function

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

View Source

Generates a number input.

See text_input/3 for example and docs.

Link to this function

options_for_select(options, selected_values)

View Source

Returns options to be used inside a select.

This is useful when building the select by hand. It expects all options and one or more select values.

Examples

options_for_select(["Admin": "admin", "User": "user"], "admin")
#=> <option value="admin" selected>Admin</option>
#=> <option value="user">User</option>

Multiple selected values:

options_for_select(["Admin": "admin", "User": "user", "Moderator": "moderator"],
  ["admin", "moderator"])
#=> <option value="admin" selected>Admin</option>
#=> <option value="user">User</option>
#=> <option value="moderator" selected>Moderator</option>

Groups are also supported:

options_for_select(["Europe": ["UK", "Sweden", "France"], ...], nil)
#=> <optgroup label="Europe">
#=>   <option>UK</option>
#=>   <option>Sweden</option>
#=>   <option>France</option>
#=> </optgroup>
Link to this function

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

View Source

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.

Link to this function

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

View Source

Generates a radio button.

Invoke this function for each possible value you want 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.

Link to this function

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

View Source

Generates a range input.

See text_input/3 for example and docs.

Link to this function

reset(value, opts \\ [])

View Source

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">
Link to this function

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

View Source

Generates a search input.

See text_input/3 for example and docs.

Link to this function

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

View Source

Generates a select tag with the given options.

options are expected to be an enumerable which will be used to generate each respective option. The enumerable may have:

  • keyword lists - each keyword list is expected to have the keys :key and :value. Additional keys such as :disabled may be given to customize the option.

  • two-item tuples - where the first element is an atom, string or integer to be used as the option label and the second element is an atom, string or integer to be used as the option value

  • atom, string or integer - which will be used as both label and value for the generated select

Optgroups

If options is map or keyword list where the first element is a string, atom or integer and the second element is a list or a map, it is assumed the key will be wrapped in an <optgroup> and the value will be used to generate <options> nested under the group.

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, [[key: "Admin", value: "admin", disabled: true],
                     [key: "User", value: "user"]])
#=> <select id="user_role" name="user[role]">
#=>   <option value="admin" disabled="disabled">Admin</option>
#=>   <option value="user">User</option>
#=> </select>

You can also pass a prompt:

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>

And customize the prompt like any other entry:

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

If you want to select an option that comes from the database, such as a manager for a given project, you may write:

select(form, :manager_id, Enum.map(@managers, &{&1.name, &1.id}))
#=> <select id="manager_id" name="project[manager_id]">
#=>   <option value="1">Mary Jane</option>
#=>   <option value="2">John Doe</option>
#=> </select>

Finally, if the values are a list or a map, we use the keys for grouping:

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>

Options

  • :prompt - an option to include at the top of the options. It may be a string or a keyword list of attributes and the :key

  • :selected - the default value to use when none was sent as parameter

Be aware that a :multiple option will not generate a correctly functioning multiple select element. Use multiple_select/4 instead.

All other options are forwarded to the underlying HTML tag.

Generates a submit button to send the form.

Examples

submit do: "Submit"
#=> <button type="submit">Submit</button>
Link to this function

submit(value, opts \\ [])

View Source

Generates a submit button to send the form.

All options are forwarded to the underlying button tag. When called with a do: block, the button tag options come first.

Examples

submit "Submit"
#=> <button type="submit">Submit</button>

submit "Submit", class: "btn"
#=> <button class="btn" type="submit">Submit</button>

submit [class: "btn"], do: "Submit"
#=> <button class="btn" type="submit">Submit</button>
Link to this function

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

View Source

Generates a telephone input.

See text_input/3 for example and docs.

Link to this function

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

View Source

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="">
Link to this function

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

View Source

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.

Therefore, 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.

Link to this function

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

View Source

Generates a time input.

Options

  • :precision - Allowed values: :minute, :second, :millisecond. Defaults to :minute.

All other options are forwarded. See text_input/3 for example and docs.

Examples

time_input form, :time
#=> <input id="form_time" name="form[time]" type="time" value="23:00">

time_input form, :time, precision: :second
#=> <input id="form_time" name="form[time]" type="time" value="23:00:00">

time_input form, :time, precision: :millisecond
#=> <input id="form_time" name="form[time]" type="time" value="23:00:00.000">
Link to this function

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

View Source

Generates select tags for time.

Warning: This functionality is best provided by browsers nowadays. Consider using time_input/3 instead.

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

Link to this function

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

View Source

Generates an url input.

See text_input/3 for example and docs.