Corex.DatePicker
(Corex v0.1.0-alpha.29)
View Source
Phoenix implementation of Zag.js Date Picker.
Examples
Basic Usage
This example assumes the import of .icon from Core Components
<.date_picker id="my-date-picker">
<:label>Select a date</:label>
<:trigger>
<.icon name="hero-calendar" />
</:trigger>
<:prev_trigger>
<.icon name="hero-chevron-left" class="icon" />
</:prev_trigger>
<:next_trigger>
<.icon name="hero-chevron-right" class="icon" />
</:next_trigger>
</.date_picker>Controlled Mode
This example assumes the import of .icon from Core Components
<.date_picker
id="my-date-picker"
controlled
value={@date_value}
on_value_change="date_changed">
<:label>Select a date</:label>
<:trigger>
<.icon name="hero-calendar" />
</:trigger>
<:prev_trigger>
<.icon name="hero-chevron-left" class="icon" />
</:prev_trigger>
<:next_trigger>
<.icon name="hero-chevron-right" class="icon" />
</:next_trigger>
</.date_picker>def handle_event("date_changed", %{"value" => value}, socket) do
{:noreply, assign(socket, :date_value, value)}
endPhoenix Form Integration
When using with Phoenix forms, you must add an id to the form using the Corex.Form.get_form_id/1 function.
Controller
defmodule MyAppWeb.PageController do
use MyAppWeb, :controller
def home(conn, params) do
form = Phoenix.Component.to_form(Map.get(params, "user", %{}), as: :user)
render(conn, :home, form: form)
end
end<.form :let={f} as={:user} for={@form} id={get_form_id(@form)} method="get">
<.date_picker field={f[:birth_date]} class="date-picker">
<:label>Birth date</:label>
<:trigger>
<.icon name="hero-calendar" class="icon" />
</:trigger>
<:prev_trigger>
<.icon name="hero-chevron-left" class="icon" />
</:prev_trigger>
<:next_trigger>
<.icon name="hero-chevron-right" class="icon" />
</:next_trigger>
<:error :let={msg}>
<.icon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
</.date_picker>
<button type="submit">Submit</button>
</.form>Live View
When using Phoenix form in a Live view you must also add controlled mode. This allows the Live view to be the source of truth and the component to be in sync accordingly.
defmodule MyAppWeb.DatePickerLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
form = to_form(%{"birth_date" => nil}, as: :user)
{:ok, assign(socket, :form, form)}
end
def render(assigns) do
~H"""
<.form as={:user} for={@form} id={get_form_id(@form)}>
<.date_picker field={@form[:birth_date]} class="date-picker" controlled>
<:label>Birth date</:label>
<:trigger>
<.icon name="hero-calendar" class="icon" />
</:trigger>
<:prev_trigger>
<.icon name="hero-chevron-left" class="icon" />
</:prev_trigger>
<:next_trigger>
<.icon name="hero-chevron-right" class="icon" />
</:next_trigger>
<:error :let={msg}>
<.icon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
</.date_picker>
<button type="submit">Submit</button>
</.form>
"""
end
endWith Ecto changeset
When using Ecto changeset for validation and inside a Live view you must enable the controlled mode.
This allows the Live View to be the source of truth and the component to be in sync accordingly.
First create your schema and changeset:
defmodule MyApp.Accounts.User do
use Ecto.Schema
import Ecto.Changeset
schema "users" do
field :name, :string
field :birth_date, :date
timestamps(type: :utc_datetime)
end
def changeset(user, attrs) do
user
|> cast(attrs, [:name, :birth_date])
|> validate_required([:name, :birth_date])
end
enddefmodule MyAppWeb.UserLive do
use MyAppWeb, :live_view
alias MyApp.Accounts.User
def mount(_params, _session, socket) do
{:ok, assign(socket, :form, to_form(User.changeset(%User{}, %{})))}
end
def handle_event("validate", %{"user" => user_params}, socket) do
changeset = User.changeset(%User{}, user_params)
{:noreply, assign(socket, form: to_form(changeset, action: :validate))}
end
def render(assigns) do
~H"""
<.form for={@form} id={get_form_id(@form)} phx-change="validate">
<.date_picker field={@form[:birth_date]} class="date-picker" controlled>
<:label>Birth date</:label>
<:trigger>
<.icon name="hero-calendar" class="icon" />
</:trigger>
<:prev_trigger>
<.icon name="hero-chevron-left" class="icon" />
</:prev_trigger>
<:next_trigger>
<.icon name="hero-chevron-right" class="icon" />
</:next_trigger>
<:error :let={msg}>
<.icon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
</.date_picker>
</.form>
"""
end
endAPI Control
In order to use the API, you must use an id on the component
Client-side
<button phx-click={Corex.DatePicker.set_value("my-date-picker", "2024-01-15")}>
Set Date
</button>Server-side
def handle_event("set_date", _, socket) do
{:noreply, Corex.DatePicker.set_value(socket, "my-date-picker", "2024-01-15")}
endStyling
Use data attributes to target elements:
[data-scope="date-picker"][data-part="root"] {}
[data-scope="date-picker"][data-part="label"] {}
[data-scope="date-picker"][data-part="control"] {}
[data-scope="date-picker"][data-part="input"] {}
[data-scope="date-picker"][data-part="trigger"] {}
[data-scope="date-picker"][data-part="positioner"] {}
[data-scope="date-picker"][data-part="content"] {}If you wish to use the default Corex styling, you can use the class date-picker on the component.
This requires to install Mix.Tasks.Corex.Design first and import the component css file.
@import "../corex/main.css";
@import "../corex/tokens/themes/neo/light.css";
@import "../corex/components/date-picker.css";You can then use modifiers
<.date_picker class="date-picker date-picker--accent date-picker--lg" id="my-date-picker">
</.date_picker>Learn more about modifiers and Corex Design
Summary
API
Sets the date picker value from client-side. Returns a Phoenix.LiveView.JS command.
Sets the date picker value from server-side. Pushes a LiveView event.
Functions
Renders a date picker component.
API
Sets the date picker value from client-side. Returns a Phoenix.LiveView.JS command.
Examples
<button phx-click={Corex.DatePicker.set_value("my-date-picker", "2024-01-15")}>
Set Date
</button>
Sets the date picker value from server-side. Pushes a LiveView event.
Examples
def handle_event("set_date", _params, socket) do
socket = Corex.DatePicker.set_value(socket, "my-date-picker", "2024-01-15")
{:noreply, socket}
end
Functions
Renders a date picker component.
Attributes
id(:string) - The unique identifier for the date picker. Set automatically when using the field attr. Defaults tonil.value(:string) - The initial value or the controlled value (ISO date string). Defaults tonil.controlled(:boolean) - Whether the date picker is controlled. Only in LiveView, the on_value_change event is required. Defaults tofalse.locale(:string) - The locale for date formatting. Defaults tonil.time_zone(:string) - The time zone for date operations. Defaults tonil.dir(:string) - The direction of the date picker. When nil, derived from document (html lang + config :rtl_locales). Defaults tonil. Must be one ofnil,"ltr", or"rtl".on_value_change(:string) - The server event name when the value changes. Defaults tonil.on_focus_change(:string) - The server event name when focus changes. Defaults tonil.on_view_change(:string) - The server event name when the view changes. Defaults tonil.name(:string) - The name attribute of the input element. Defaults tonil.disabled(:boolean) - Whether the calendar is disabled. Defaults tofalse.read_only(:boolean) - Whether the calendar is read-only. Defaults tofalse.required(:boolean) - Whether the date picker is required. Defaults tofalse.invalid(:boolean) - Whether the date picker is invalid. Defaults tofalse.outside_day_selectable(:boolean) - Whether day outside the visible range can be selected. Defaults tofalse.close_on_select(:boolean) - Whether the calendar should close after the date selection is complete. Defaults totrue.min(:string) - The minimum date that can be selected (ISO date string). Defaults tonil.max(:string) - The maximum date that can be selected (ISO date string). Defaults tonil.focused_value(:string) - The initial focused date when the calendar opens (ISO date string). Used as default in the picker. Defaults tonil.num_of_months(:integer) - The number of months to display. Defaults to1.start_of_week(:integer) - The first day of the week (0=Sunday, 1=Monday, etc.). Defaults to0.fixed_weeks(:boolean) - Whether the calendar should have a fixed number of weeks (6 weeks). Defaults totrue.selection_mode(:string) - The selection mode of the calendar. Defaults to"single". Must be one of"single","multiple", or"range".placeholder(:string) - The placeholder text to display in the input. Defaults tonil.trigger_aria_label(:string) - Accessible name for the trigger button when it contains only an icon (e.g. "Select date"). Defaults tonil.input_aria_label(:string) - Accessible name for the input when it's not associated with a visible label (e.g. "Select date"). Defaults tonil.default_view(:string) - The initial view of the calendar (day, month, or year). Defaults to"day". Must be one of"day","month", or"year".min_view(:string) - The minimum view of the calendar. Defaults to"day". Must be one of"day","month", or"year".max_view(:string) - The maximum view of the calendar. Defaults to"year". Must be one of"day","month", or"year".positioning(Corex.Positioning) - Positioning options for the date picker content. Defaults to%Corex.Positioning{hide_when_detached: true, strategy: "fixed", placement: "bottom", gutter: 8, shift: 0, overflow_padding: 0, arrow_padding: 4, flip: true, slide: true, overlap: false, same_width: true, fit_viewport: false}.on_visible_range_change(:string) - The server event name when the visible range changes. Defaults tonil.on_open_change(:string) - The server event name when the calendar opens or closes. Defaults tonil.errors(:list) - List of error messages to display. Defaults to[].field(Phoenix.HTML.FormField) - A form field struct from the form, e.g. @form[:birth_date]. Sets id, name, value, and errors from the field; enables controlled mode for LiveView.- Global attributes are accepted.
Slots
label- Accepts attributes:class(:string)
error- Accepts attributes:class(:string)
trigger- Accepts attributes:class(:string)
prev_trigger- Accepts attributes:class(:string)
next_trigger- Accepts attributes:class(:string)