Components
Date picker
Date picker
A calendar in a panel under a real text input. Type 14 Mar 2027
and the grid follows as the year lands; Enter commits and closes; the form posts ISO 8601 either way.
Input plus calendar
The input shows a formatted date you can type into; a hidden input posts ISO 8601 whatever the display format is. Click the calendar icon, or press Escape to close and land back on the input.
<.date_picker
id="showcase-date-picker"
name="due_on"
label="Due date"
value={~D[2026-03-14]}
format="%d %b %Y"
clearable
/>
Two-month range
Range mode posts from and to sub-fields. two_months puts the second pane beside the first, which is what a booking flow wants.
<.date_picker
id="showcase-date-picker-range"
name="stay"
mode="range"
label="Stay"
two_months
format="%d %b"
value={{~D[2026-03-09], ~D[2026-03-17]}}
/>
Field surface
Errors, help text and the required marker come from the same field surface as <.field>, so a picker sits in a form without looking bolted on.
can't be blank
We only take bookings from tomorrow.
<.date_picker
id="showcase-date-picker-errors"
name="starts_on"
label="Start date"
required
placeholder="Pick a start date"
help_text="We only take bookings from tomorrow."
errors={["can't be blank"]}
/>
Properties
| Attribute | Type | Default | Description |
|---|---|---|---|
class
|
any |
nil
|
extra classes for the wrapper |
clear_label
|
string |
"Clear date"
|
accessible label for the clear button |
clearable
|
boolean |
false
|
show a clear button whenever the field holds text |
day_names
|
list |
nil
|
7 short day labels ordered Monday-first |
day_names_long
|
list |
nil
|
7 full day labels ordered Monday-first |
disabled
|
boolean |
false
|
disable the input and the panel |
disabled_dates
|
any |
nil
|
a list of Dates, or a 1-arity function Date -> boolean |
errors
|
list |
[]
|
error messages rendered under the input |
field
|
{:struct, Phoenix.HTML.FormField} |
nil
|
a form field; wires name, value, errors and label like <.field> |
fixed_weeks
|
boolean |
false
|
always render 6 week rows |
format
|
string |
"%Y-%m-%d"
|
strftime format for the display input (Calendar.strftime/2); the posted value is always ISO 8601 |
help_text
|
string |
nil
|
context shown under the input |
id
|
string |
the picker id; autogenerated if not set | |
label
|
string |
nil
|
the field label; omitted when nil |
max
|
any |
nil
|
latest selectable Date (inclusive) |
min
|
any |
nil
|
earliest selectable Date (inclusive) |
mode
|
string |
"single"
|
selection behaviour
one of: "single", "range"
|
month
|
any |
nil
|
the displayed month as any Date within it |
month_names
|
list |
nil
|
12 month labels |
name
|
any |
nil
|
the posted field name; derived from field when given |
on_clear
|
any |
nil
|
event pushed when the clear button is clicked |
on_month_change
|
any |
nil
|
event pushed by the prev/next month buttons |
on_select
|
any |
nil
|
event pushed when a day is clicked, with the ISO date |
open_label
|
string |
"Choose date"
|
accessible label for the toggle button |
panel_class
|
any |
nil
|
extra classes for the panel |
placeholder
|
string |
nil
|
placeholder for the display input |
range_separator
|
string |
" - "
|
what sits between the two dates in the display input in range mode |
required
|
boolean |
false
|
mark the field required |
rest
|
global |
||
show_outside_days
|
boolean |
true
|
render adjacent-month days in the grid |
starts_on
|
integer |
1
|
first day of the week, ISO day numbers (1 = Monday, 7 = Sunday)
one of: 1, 2, 3, 4, 5, 6, 7
|
target
|
any |
nil
|
phx-target for the picker's events |
today
|
any |
nil
|
the date treated as today; defaults to Date.utc_today/0 |
two_months
|
boolean |
false
|
render two month panes side by side. A range reads naturally across the pair, and single mode earns it too - the flight-search pattern, where seeing next month saves a page before the date you are really after |
value
|
any |
nil
|
a Date, an ISO string, or a {from, to} pair in range mode |