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-popupAttributes
x-h-datetime-picker
| Attribute | Values | Required | Description |
|---|---|---|---|
| data-size | smdefault | false | Changes the size of the date time picker. |
Modifiers
| Modifier | Description |
|---|---|
| table | Use when the input is inside a table |
x-h-datetime-picker-popup
| Attribute | Values | Required | Description |
|---|---|---|---|
| data-align | string | false | Aligns the popover relative to the trigger (e.g. bottom-start, top). |
| data-aria-prev-year | string | false | Sets the aria-label attribute value for the previous year button. |
| data-aria-prev-month | string | false | Sets the aria-label attribute value for the previous month button. |
| data-aria-next-month | string | false | Sets the aria-label attribute value for the next month button. |
| data-aria-next-year | string | false | Sets the aria-label attribute value for the next year button. |
| data-aria-choose-month | string | false | Sets the text after the month name in the month button's aria-label. Defaults to choose month. |
| data-aria-choose-year | string | false | Sets the text after the year in the year button's aria-label. Defaults to choose year. |
| data-label-time | string | false | aria-label for the time editor group (default "Time"). |
| data-label-hours | string | false | aria-label for the hour segment (default "Hour"). |
| data-label-minutes | string | false | aria-label for the minute segment (default "Minute"). |
| data-label-seconds | string | false | aria-label for the second segment (default "Second"). |
| data-label-meridiem | string | false | aria-label for the AM/PM segment (default "AM/PM"). |
| data-label-now | string | false | Text 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">:
'2025-06-25T14:30'; // without seconds
'2025-06-25T14:30:00'; // with secondsThe 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
| Event | Description |
|---|---|
| change | Fired 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.
| Key | Description |
|---|---|
| is12Hour | When true, the time editor shows a 12-hour clock with an AM/PM segment. |
| seconds | When 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
| Slot | Element |
|---|---|
datetime-picker | x-h-datetime-picker |
cell-input-datetime | x-h-datetime-picker.table |
datetime-picker-trigger | x-h-datetime-picker-trigger |
datetime-picker-calendar | x-h-datetime-picker-popup |
Examples
<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
<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
<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.
<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.
<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.
<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.
<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
<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.
<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.
<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.
<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>