View Source Phoenix.WebComponent.FormHelper (Phoenix.WebComponent v1.6.3)

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 limited data - when a form is created without an underlying data layer. In this scenario, you can use the connection information (aka Plug.Conn.params) or pass the form values by hand

  • outside of a form - when the functions are used directly, outside of form_for

We will explore all three scenarios below.

with-changeset-data

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>
    <%= wc_text_input f, :name %>
  </label>

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

  <%= wc_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

A note on :errors

If no action has been applied to the changeset or action was set to :ignore, no errors are shown on the form object even if the changeset has a non-empty :errors value.

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.

Ecto automatically applies the action for you when you call Repo.insert/update/delete, but 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.

with-limited-data

With limited data

form_for/4 expects as first argument any data structure that implements the Phoenix.WebComponent.FormData protocol. By default, Phoenix implements this protocol for Plug.Conn and Atom.

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, Routes.foo_path(@conn, :new), [as: :foo], fn f -> %>
  <%= wc_text_input f, :for %>
  <%= wc_submit "Search" %>
<% end %>

form_for/4 uses the Plug.Conn to set input values from the request parameters.

Alternatively, if you don't have a connection, you can pass :foo as the form data source and explicitly pass the value for every input:

<%= form_for :foo, Routes.foo_path(MyApp.Endpoint, :new), fn f -> %>
  <%= wc_text_input f, :for, value: "current value" %>
  <%= wc_submit "Search" %>
<% end %>

without-form-data

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.

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

Link to this section Summary

Functions

Returns options to be used inside a select.

Generates a wc_checkbox.

Generates a color input.

Generates a date input.

Generates an email input.

Generates a file input.

Generates a select tag with the given options.

Generates a number input.

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

Generates a wc_submit button to send the form.

Generates a telephone input.

Generates a text input.

Generates a textarea input.

Generates an url input.

Link to this section Functions

Link to this function

options_for_select(options)

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

Examples

options_for_select(["Admin": "admin", "User": "user"], "admin")
#=> <option value="admin" selected="selected">Admin</option>
#=> <option value="user">User</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

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

View Source

Generates a wc_checkbox.

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

examples

Examples

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

options

Options

  • :checked_value - the value to be sent when the wc_checkbox is checked. Defaults to "true"

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

  • :unchecked_value - the value to be sent when the wc_checkbox is unchecked, Defaults to "false"

  • :value - the value used to check if a wc_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

Hidden fields

Because an unchecked wc_checkbox is not sent to the server, Phoenix automatically generates a hidden field with the unchecked_value before the wc_checkbox field to ensure the unchecked_value is sent when the wc_checkbox is not marked. Set hidden_input to false If you don't want to send values from unchecked wc_checkbox to the server.

Link to this function

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

View Source

Generates a color input.

Warning: this feature isn't available in all browsers. Check http://caniuse.com/#feat=input-color for further information.

See text_input/3 for example and docs.

Link to this function

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

View Source

Generates a date input.

Warning: this feature isn't available in all browsers. Check http://caniuse.com/#feat=input-datetime for further information.

See text_input/3 for example and docs.

Link to this function

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

View Source

Generates an email input.

Auto add pattern="[^@]+@[^@]+" to check format

See text_input/3 for example and docs.

Link to this function

wc_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 wc_text_input/3 for example and docs.

Link to this function

wc_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

Examples

# Assuming form contains a User schema
wc_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>

wc_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:

wc_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

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

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

View Source
@spec wc_number_input(atom() | Phoenix.HTML.Form.t(), atom() | binary(), keyword()) ::
  {:safe, [binary() | list() | 60 | 62, ...]}

Generates a number input.

See text_input/3 for example and docs.

Link to this function

wc_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

wc_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

Examples

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

options

Options

All options are simply forwarded to the underlying HTML tag.

Link to this function

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

View Source

Generates a range input.

See text_input/3 for example and docs.

Link to this function

wc_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

Examples

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

wc_reset "Reset", class: "btn"
#=> <input type="reset" value="Reset" class="btn">
Link to this function

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

View Source

Generates a search input.

See text_input/3 for example and docs.

Link to this function

wc_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

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

Examples

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

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

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

You can also pass a prompt:

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

And customize the prompt as any other entry:

select(form, :role, ["Admin": "admin", "User": "user"], prompt: [key: "Choose your role", disabled: true])
#=> <bx-select id="user_role" name="user[role]">
#=>   <option value="" disabled="">Choose your role</option>
#=>   <option value="admin">Admin</option>
#=>   <option value="user">User</option>
#=> </bx-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}))
#=> <bx-select id="manager_id" name="project[manager_id]">
#=>   <option value="1">Mary Jane</option>
#=>   <option value="2">John Doe</option>
#=> </bx-select>

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

select(form, :country, ["Europe": ["UK", "Sweden", "France"]], ...)
#=> <bx-select id="user_country" name="user[country]">
#=>   <optgroup label="Europe">
#=>     <option>UK</option>
#=>     <option>Sweden</option>
#=>     <option>France</option>
#=>   </optgroup>
#=>   ...
#=> </bx-select>

options

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 wc_multiple_select/4 instead.

All other options are forwarded to the underlying HTML tag.

Generates a wc_submit button to send the form.

examples

Examples

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

wc_submit(value, opts \\ [])

View Source

Generates a wc_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

Examples

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

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

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

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

View Source

## Examples

# Assuming form contains a User schema
wc_switch(form, :enable, [checked_value: "yes", unchecked_value: "no"])
#=> <bx-toggle id="user_enable" name="user[enable]" value="yes" />

options

Options

  • :checked_value - the value if the switch is on, Defaults to "true".
  • :unchecked_value - the value if the switch is off, Defaults to "false"
  • :value - the value of checked_value or unchecked_value.
Link to this function

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

View Source

Generates a telephone input.

See text_input/3 for example and docs.

Link to this function

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

View Source

Generates a text input.

The form should either be a Phoenix.WebComponent.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

Examples

# Assuming form contains a User schema
wc_text_input(form, :name)
#=> <bx-input id="user_name" name="user[name]" type="text" value="" />

wc_text_input(:user, :name)
#=> <bx-input id="user_name" name="user[name]" type="text" value="" />
Link to this function

wc_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

Examples

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

new-lines

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.

Link to this function

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

View Source

Generates an url input.

See text_input/3 for example and docs.