Skip to content

Date Time Picker ​

Lets users pick a date and a time together. The date is chosen from a calendar and the time is set in a compact segmented editor below it, all within a single popover so it stays usable on narrow screens.

Usage ​

Use the Date Time Picker when a single value needs both a calendar date and a time of day (e.g. scheduling an appointment). For a date only, use the Date Picker. For a time only, use the Time Picker.

The date is selected in the calendar. The time is set by focusing a segment (hour, minute, optional second, optional AM/PM) and pressing the arrow keys, like a native time field. The popover stays open while you adjust both date and time, and closes on Escape or an outside click.

Keyboard Handling ​

In the calendar grid:

  • Up / Down / Left / Right - Move the focused day.
  • Enter / Space - Select the focused day. Pressing it on the already selected day deselects it.
  • Home / End - First / last day of the month.
  • PageUp / PageDown - Previous / next month.

In the month and year selection grids:

  • Up / Down / Left / Right - Move the focused month or year.
  • Home / End - First / last month or year.
  • PageUp / PageDown - 12 years back / forward in the year grid.
  • Enter / Space - Show the days of the focused month or year.
  • Tab / Shift+Tab - Cycle between the calendar header buttons and the grid. The time editor is reached again after returning to the days.
  • Esc - Return to the days.

In the time editor:

  • Tab / Left / Right - Move between the hour, minute, second and AM/PM segments.
  • 0-9 - Type the value directly. The segment fills and focus auto-advances to the next one, just like a native time input. On touch devices the numeric keyboard is shown.
  • A / P - Set the AM/PM segment (or tap it to toggle).
  • Up / Down - Increase / decrease the focused segment (wraps around).
  • Home / End - Set the focused segment to its minimum / maximum.
  • Backspace / Delete - Clear the focused segment.
  • Esc - Close the popover and return focus to the control that opened it.

Tab and Shift+Tab move through the calendar, the time editor and the "Now" button, and stay inside the open popover.

Accessibility ​

The calendar is exposed as an ARIA date grid (see the Inline Calendar accessibility notes). Its month and year are toggle buttons that open a month grid or a year list in place of the days, as described in the Inline Calendar behavior. Each time segment is a spinbutton with its own label and aria-valuemin / aria-valuemax / aria-valuenow / aria-valuetext, so assistive technology announces it and its current value. The trigger advertises aria-haspopup="dialog" and its expanded state.

API Reference ​

Component attribute(s) ​

x-h-datetime-picker
x-h-datetime-picker-trigger
x-h-datetime-picker-popup

Attributes ​

x-h-datetime-picker ​

AttributeValuesRequiredDescription
data-sizesm
default
falseChanges the size of the date time picker.

Modifiers ​

ModifierDescription
tableUse when the input is inside a table

x-h-datetime-picker-popup ​

AttributeValuesRequiredDescription
data-alignstringfalseAligns the popover relative to the trigger (e.g. bottom-start, top).
data-aria-prev-yearstringfalseSets the aria-label attribute value for the previous year button.
data-aria-prev-monthstringfalseSets the aria-label attribute value for the previous month button.
data-aria-next-monthstringfalseSets the aria-label attribute value for the next month button.
data-aria-next-yearstringfalseSets the aria-label attribute value for the next year button.
data-aria-choose-monthstringfalseSets the text after the month name in the month button's aria-label. Defaults to choose month.
data-aria-choose-yearstringfalseSets the text after the year in the year button's aria-label. Defaults to choose year.
data-label-timestringfalsearia-label for the time editor group (default "Time").
data-label-hoursstringfalsearia-label for the hour segment (default "Hour").
data-label-minutesstringfalsearia-label for the minute segment (default "Minute").
data-label-secondsstringfalsearia-label for the second segment (default "Second").
data-label-meridiemstringfalsearia-label for the AM/PM segment (default "AM/PM").
data-label-nowstringfalseText label for the Now button (default "Now").

Model ​

When using x-model, the picker reads and writes a single ISO date-time string with a T separator, matching a native <input type="datetime-local">:

js
'2025-06-25T14:30'; // without seconds
'2025-06-25T14:30:00'; // with seconds

The time is always stored in 24-hour form regardless of the display format. The model is set only when both a date and a complete time have been chosen. Until then it is an empty string. Clicking the selected day in the calendar again deselects it, returning the model to an empty string until a day is picked again.

Events ​

EventDescription
changeFired on the inner input whenever user interaction produces a new combined date and time value. It does not fire while the value is still incomplete (e.g. a date is picked but no time yet) or for programmatic model changes. The event bubbles, so a listener can be placed on the x-h-datetime-picker element. Read the new value from the bound model, as the input's own value holds the display text.

There is no need to use $watch to react to user selection - listen for change instead. See Listening for changes.

Configuration ​

You can pass a configuration object to the popup as an expression or as a value. It accepts every Date Picker calendar key (locale, firstDay, min, max, options, delimiter, order) plus the time keys below.

KeyDescription
is12HourWhen true, the time editor shows a 12-hour clock with an AM/PM segment.
secondsWhen true, the time editor includes a seconds segment. Inferred from the model when unset.

Validation timing ​

By default this control shows native-constraint errors (for example required) only after the user interacts with it or attempts to submit, not on page load. To validate on load instead, set data-validate="immediate" on a wrapping x-h-fieldset, x-h-field, or any ancestor element. Setting aria-invalid="true" yourself always shows the error immediately. See Fieldset for details.

Data Slots ​

SlotElement
datetime-pickerx-h-datetime-picker
cell-input-datetimex-h-datetime-picker.table
datetime-picker-triggerx-h-datetime-picker-trigger
datetime-picker-calendarx-h-datetime-picker-popup

Examples ​

html
<div x-h-datetime-picker x-data="{ dt: '' }">
  <input type="text" id="datetime-input-1" />
  <button x-h-datetime-picker-trigger aria-label="Choose date and time"></button>
  <div x-h-datetime-picker-popup x-model="dt"></div>
</div>

Listening for changes ​

html
<div x-h-datetime-picker x-data="{ dt: '' }" @change="console.log('Selected date and time:', dt)">
  <input type="text" id="datetime-input-3" />
  <button x-h-datetime-picker-trigger aria-label="Choose date and time"></button>
  <div x-h-datetime-picker-popup x-model="dt"></div>
</div>

12-hour with seconds ​

html
<div x-h-datetime-picker x-data="{ dt: '' }">
  <input type="text" id="datetime-input-2" />
  <button x-h-datetime-picker-trigger aria-label="Choose date and time"></button>
  <div x-h-datetime-picker-popup="{ is12Hour: true, seconds: true }" x-model="dt"></div>
</div>

With locale ​

The locale sets the date's display format and the calendar's month and day names. The time keeps its 24-hour or 12-hour form.

html
<div x-h-datetime-picker x-data="{ dt: '2026-07-09T14:30' }">
  <input type="text" id="datetime-input-locale" />
  <button x-h-datetime-picker-trigger aria-label="Choose date and time"></button>
  <div x-h-datetime-picker-popup="{ locale: 'de-DE', firstDay: 1 }" x-model="dt"></div>
</div>

With translated labels ​

Translate the trigger's aria-label, the calendar's data-aria-* labels and the time editor's data-label-* labels along with the locale, so screen readers announce every control in the page's language.

html
<div x-h-datetime-picker x-data="{ dt: '2026-07-09T14:30' }">
  <input type="text" id="datetime-input-labels" />
  <button x-h-datetime-picker-trigger aria-label="Изберете дата и час"></button>
  <div
    x-h-datetime-picker-popup="{ locale: 'bg-BG', firstDay: 1 }"
    x-model="dt"
    data-aria-prev-year="предишна година"
    data-aria-prev-month="предишен месец"
    data-aria-next-month="следващ месец"
    data-aria-next-year="следваща година"
    data-aria-choose-month="изберете месец"
    data-aria-choose-year="изберете година"
    data-label-time="Час"
    data-label-hours="Часове"
    data-label-minutes="Минути"
    data-label-now="Сега"
  ></div>
</div>

With min and max dates ​

Days before min and after max cannot be selected. The back/forward buttons stop at July and August, and the month grid and year list hold only the months and years inside the range.

html
<div x-h-datetime-picker x-data="{ dt: '2026-07-09T09:30' }">
  <input type="text" id="datetime-input-min-max" />
  <button x-h-datetime-picker-trigger aria-label="Choose date and time"></button>
  <div x-h-datetime-picker-popup="{ min: '2026-07-01', max: '2026-08-31' }" x-model="dt"></div>
</div>

With custom date format ​

The options, order and delimiter keys shape the date part of the display. The time follows it unchanged.

html
<div x-h-datetime-picker x-data="{ dt: '2026-07-09T14:30' }">
  <input type="text" id="datetime-input-format" />
  <button x-h-datetime-picker-trigger aria-label="Choose date and time"></button>
  <div x-h-datetime-picker-popup="{ options: { year: 'numeric', month: '2-digit', day: '2-digit' }, order: 'YMD', delimiter: '-' }" x-model="dt"></div>
</div>

Small ​

html
<div x-h-datetime-picker data-size="sm" x-data="{ dt: '2026-07-09T14:30' }">
  <input type="text" id="datetime-input-sm" />
  <button x-h-datetime-picker-trigger aria-label="Choose date and time"></button>
  <div x-h-datetime-picker-popup x-model="dt"></div>
</div>

Invalid ​

Reacts to the native invalid state or to the aria-invalid attribute.

html
<div x-h-datetime-picker x-data="{ dt: '2026-07-09T14:30' }">
  <input type="text" id="datetime-input-invalid" aria-invalid="true" />
  <button x-h-datetime-picker-trigger aria-label="Choose date and time"></button>
  <div x-h-datetime-picker-popup x-model="dt"></div>
</div>

Disabled ​

Set the native disabled attribute on the inner input to disable the whole picker.

html
<div x-h-datetime-picker x-data="{ dt: '2026-07-09T14:30' }">
  <input type="text" id="datetime-input-disabled" disabled />
  <button x-h-datetime-picker-trigger aria-label="Choose date and time"></button>
  <div x-h-datetime-picker-popup x-model="dt"></div>
</div>

Read-only ​

Set the native readonly attribute on the inner input. The value is shown with a muted background, and the popover cannot change it.

html
<div x-h-datetime-picker x-data="{ dt: '2026-07-09T14:30' }">
  <input type="text" id="datetime-input-readonly" readonly />
  <button x-h-datetime-picker-trigger aria-label="Choose date and time"></button>
  <div x-h-datetime-picker-popup x-model="dt"></div>
</div>