What a picker posts
A picker posts what the browser's own <select> would:
- a picker of one value:
task[status]=doing, ortask[status]=when it is empty; - a picker of several:
task[labels][]=and then onetask[labels][]for each value, in the order people chose them. The empty one first means that a picker with no value clears the field, as a list of checkboxes with a hidden input does.
So the params cast into an Ecto.Enum, an :integer id, a :string,
or an {:array, _} field, with cast/3 as they are.
The picker writes its value into a native <select> and tells the form
(input and change events), so phx-change sees each change, and a
form without LiveView posts it.
Before the hook mounts
Until its hook mounts (and with JavaScript off), the picker is that
<select>: its options, its value, required, disabled. Once the
picker is ready, the <select> stays in the form, out of sight, out of
the tab order and hidden from screen readers, and keeps posting.
Changesets
Erabi.Changeset.validate_choice/4 checks the picker's rules on the
server (see Rules). Give it the options the value must be
among, or a function of the posted values for options that come from a
search:
|> Erabi.Changeset.validate_choice(:status, [required: true], options: @statuses)
|> Erabi.Changeset.validate_choice(:owner_id, [], options: &Accounts.existing_ids/1)Errors
A field with errors (and used_input?/1) marks the picker
aria-invalid; give the id of the error's element as
aria-describedby, as for an input:
<.select field={@form[:status]} options={@statuses} aria-describedby="status-error" />
<p :for={msg <- @form[:status].errors} id="status-error">{translate_error(msg)}</p>Labels
A <label for> of the field names the picker, and a click on it moves
the focus to the picker:
<label for={@form[:status].id}>Status</label>
<.select field={@form[:status]} options={@statuses} />Or give label_id (the id of an element that names it), or label (the
name itself). Without any, the picker is named by its field, in words.
A required picker
required is a rule (a value must be chosen), the native <select>'s
required, and no clear button. When the browser stops a submit for an
empty required picker, the picker takes the focus and says so.