Localize.Inputs.Date.Components (Localize.Inputs.Date v0.1.1)

Copy Markdown View Source

HEEx components for locale-aware date form input.

Provides date_input/1, date_range_input/1, and date_range_picker/1. Built on calendrical for multi-calendar parsing (Gregorian, Buddhist, Japanese, Islamic, Persian, Hebrew, ROC, …).

Setup

Add the JS hooks in your assets/js/app.js:

import Hooks from "localize_datetime_inputs"
let liveSocket = new LiveSocket("/live", Socket, {
  hooks: {
    DatePicker: Hooks.DatePicker,
    DateRangePicker: Hooks.DateRangePicker
  }
})

Tolerance of invalid input

These components sit on the render path and never raise on bad input — the page always renders. Specifically:

  • Unknown :locale — formatting falls back to whatever Localize.Date.to_string/2 returns; on failure the cell renders the ISO-8601 form of the date (2026-05-17).

  • Unknown :calendar — date conversion uses a tolerant Date.convert/2; on failure the date is kept in its original calendar (typically Calendar.ISO) and rendered using whatever pattern lookup succeeds.

  • Blank or unparseable value — the visible text input renders empty; the hidden ISO carrier stays empty. Localize.Inputs.Date.Parser.parse_date/2 returns {:ok, nil} for blanks and {:error, %Calendrical.DateParseError{}} for garbage, never raises.

  • date_range_input/1 child field atoms — derives {field}_from and {field}_to via String.to_existing_atom/1. The atom must already exist (it does, because your changeset/schema defines it for form parsing); if it doesn't, an ArgumentError surfaces at render time and points at the missing field.

  • DatePickerLive malformed cursor / month — the server-rendered grid uses tolerant safe_convert/2 and safe_build_date/4 helpers. An invalid year/month combo for the target calendar falls back to today rather than 500ing the LiveView.

Summary

Functions

Locale-aware date input with a popup calendar grid.

Locale-aware date-range input.

Locale-aware date-range input with a unified popup calendar (click start, then click end inside the same grid). Pairs with RangePicker JS hook.

Functions

date_input(assigns)

Locale-aware date input with a popup calendar grid.

Renders a text input that accepts the locale's CLDR date patterns plus ISO-8601, paired with a calendar-icon trigger that opens a Gregorian month grid for picking. Selecting a day fills the text input (locale-formatted) and a hidden sibling input (ISO wire format). On submit the form receives params[field] as "YYYY-MM-DD".

Server-side, parse with Localize.Inputs.Date.Parser.parse_date/2 or Calendrical.Date.parse/2.

Multi-calendar parsing works (Buddhist, Islamic, Japanese, etc.) — the user can type in their locale's calendar representation and the server parses correctly. The popup grid renders in Gregorian; non-Gregorian grid rendering is a follow-on enhancement.

Attributes

  • :form — the Phoenix.HTML.Form the field belongs to.

  • :field — the form field as an atom.

  • :value — explicit ISO date string; otherwise pulled from @form[@field].

  • :locale — display locale. Defaults to Localize.get_locale/0.

  • :min, :max — ISO date strings or Date structs.

  • :placeholder — placeholder text for the text input.

  • :display_format — one of :short, :medium (default), :long, :full. Controls the locale-formatted display shape; the wire value is always ISO.

  • :js — set to false to skip the phx-hook attribute.

  • :class, :input_class, :button_class, :overlay_class — customisation hooks.

Examples

<.date_input form={@form} field={:dob} />

<.date_input
  form={@form}
  field={:start_date}
  min={~D[2026-01-01]}
  max={~D[2026-12-31]}
  display_format={:long}
/>

Attributes

  • form (Phoenix.HTML.Form) (required)
  • field (:atom) (required)
  • value (:any) - Defaults to nil.
  • locale (:any) - Defaults to nil.
  • min (:any) - Defaults to nil.
  • max (:any) - Defaults to nil.
  • placeholder (:string) - Defaults to nil.
  • display_format (:atom) - Defaults to :medium. Must be one of :short, :medium, :long, or :full.
  • calendar (:atom) - Defaults to :gregorian.
  • variant (:atom) - Defaults to :auto. Must be one of :auto, :dropdown, or :sheet.
  • js (:boolean) - Defaults to true.
  • class (:string) - Defaults to nil.
  • input_class (:string) - Defaults to nil.
  • button_class (:string) - Defaults to nil.
  • overlay_class (:string) - Defaults to nil.
  • Global attributes are accepted. Supports all globals plus: ["disabled", "readonly", "required", "autofocus"].

date_range_input(assigns)

Locale-aware date-range input.

Renders two paired text inputs (from / to) inside a single grouped wrapper. Each field is independently editable; the pair submits as params[field] = %{"from" => "YYYY-MM-DD", "to" => "YYYY-MM-DD"}.

Server-side, parse with Calendrical.Date.parse_range/2 passing the {from, to} tuple from params[field].

Attributes

  • :form — the Phoenix.HTML.Form the field belongs to.

  • :field — the form field as an atom; sub-fields submit under params[field][from] and params[field][to].

  • :locale, :min, :max, :display_format, :variant, :js — passed through to both inputs.

  • :class, :input_class, :button_class, :overlay_class — customisation hooks.

Examples

<.date_range_input form={@form} field={:stay} />

<.date_range_input
  form={@form}
  field={:trip}
  min={~D[2026-01-01]}
  max={~D[2026-12-31]}
/>

Attributes

  • form (Phoenix.HTML.Form) (required)
  • field (:atom) (required)
  • locale (:any) - Defaults to nil.
  • min (:any) - Defaults to nil.
  • max (:any) - Defaults to nil.
  • placeholder_from (:string) - Defaults to nil.
  • placeholder_to (:string) - Defaults to nil.
  • display_format (:atom) - Defaults to :medium. Must be one of :short, :medium, :long, or :full.
  • calendar (:atom) - Defaults to :gregorian.
  • variant (:atom) - Defaults to :auto. Must be one of :auto, :dropdown, or :sheet.
  • js (:boolean) - Defaults to true.
  • class (:string) - Defaults to nil.
  • input_class (:string) - Defaults to nil.
  • button_class (:string) - Defaults to nil.
  • overlay_class (:string) - Defaults to nil.

date_range_picker(assigns)

Locale-aware date-range input with a unified popup calendar (click start, then click end inside the same grid). Pairs with RangePicker JS hook.

Renders two text inputs (visible "from" and "to") plus a single shared trigger and overlay. The user clicks the trigger to open the popup, clicks once for the start, hovers to preview, clicks again for the end. Both text inputs and both hidden ISO inputs populate.

Submits as params[field] = %{"from" => "YYYY-MM-DD", "to" => "YYYY-MM-DD"}. Server-side, parse with Calendrical.Date.parse_range/2 passing the {from, to} tuple.

Attributes

Same shape as date_range_input/1: :form, :field, :locale, :min, :max, :display_format, :calendar, :variant, :js, :class, etc.

Examples

<.date_range_picker form={@form} field={:stay} />

Attributes

  • form (Phoenix.HTML.Form) (required)
  • field (:atom) (required)
  • locale (:any) - Defaults to nil.
  • min (:any) - Defaults to nil.
  • max (:any) - Defaults to nil.
  • placeholder_from (:string) - Defaults to nil.
  • placeholder_to (:string) - Defaults to nil.
  • display_format (:atom) - Defaults to :medium. Must be one of :short, :medium, :long, or :full.
  • calendar (:atom) - Defaults to :gregorian.
  • variant (:atom) - Defaults to :auto. Must be one of :auto, :dropdown, or :sheet.
  • js (:boolean) - Defaults to true.
  • class (:string) - Defaults to nil.
  • input_class (:string) - Defaults to nil.
  • button_class (:string) - Defaults to nil.
  • overlay_class (:string) - Defaults to nil.