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)}
end

Phoenix 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
end

With 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
end
defmodule 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
end

API 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")}
end

Styling

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

set_value(date_picker_id, value)

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>

set_value(socket, date_picker_id, value)

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

date_picker(assigns)

Renders a date picker component.

Attributes

  • id (:string) - The unique identifier for the date picker. Set automatically when using the field attr. Defaults to nil.
  • value (:string) - The initial value or the controlled value (ISO date string). Defaults to nil.
  • controlled (:boolean) - Whether the date picker is controlled. Only in LiveView, the on_value_change event is required. Defaults to false.
  • locale (:string) - The locale for date formatting. Defaults to nil.
  • time_zone (:string) - The time zone for date operations. Defaults to nil.
  • dir (:string) - The direction of the date picker. When nil, derived from document (html lang + config :rtl_locales). Defaults to nil. Must be one of nil, "ltr", or "rtl".
  • on_value_change (:string) - The server event name when the value changes. Defaults to nil.
  • on_focus_change (:string) - The server event name when focus changes. Defaults to nil.
  • on_view_change (:string) - The server event name when the view changes. Defaults to nil.
  • name (:string) - The name attribute of the input element. Defaults to nil.
  • disabled (:boolean) - Whether the calendar is disabled. Defaults to false.
  • read_only (:boolean) - Whether the calendar is read-only. Defaults to false.
  • required (:boolean) - Whether the date picker is required. Defaults to false.
  • invalid (:boolean) - Whether the date picker is invalid. Defaults to false.
  • outside_day_selectable (:boolean) - Whether day outside the visible range can be selected. Defaults to false.
  • close_on_select (:boolean) - Whether the calendar should close after the date selection is complete. Defaults to true.
  • min (:string) - The minimum date that can be selected (ISO date string). Defaults to nil.
  • max (:string) - The maximum date that can be selected (ISO date string). Defaults to nil.
  • focused_value (:string) - The initial focused date when the calendar opens (ISO date string). Used as default in the picker. Defaults to nil.
  • num_of_months (:integer) - The number of months to display. Defaults to 1.
  • start_of_week (:integer) - The first day of the week (0=Sunday, 1=Monday, etc.). Defaults to 0.
  • fixed_weeks (:boolean) - Whether the calendar should have a fixed number of weeks (6 weeks). Defaults to true.
  • 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 to nil.
  • trigger_aria_label (:string) - Accessible name for the trigger button when it contains only an icon (e.g. "Select date"). Defaults to nil.
  • input_aria_label (:string) - Accessible name for the input when it's not associated with a visible label (e.g. "Select date"). Defaults to nil.
  • 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 to nil.
  • on_open_change (:string) - The server event name when the calendar opens or closes. Defaults to nil.
  • 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)