Date-time picker - form fields
SvDateTimePicker in five real shapes on one form: date-only, time-only, date+time, 12-hour with spin buttons, and a min/max-constrained field. Masked inputs (type or pick), portalled dropdowns, animated calendars. The SvGrid datetime cell editor, standalone.
A live, editable Svelte 5 component example from the SvGrid gallery (Date & Time). Read the SvGrid UI component docs for the full API.
About this example
SvDateTimePicker in the five shapes a Svelte 5 form ships: a date-only field, a time-only field, a full date and time field, a 12-hour field with spin buttons and a min and max constrained field, all on one form. Each is a masked text input that can be typed or picked, with a portalled dropdown and an animated calendar, the same component the grid mounts to edit a datetime cell.
SvDateTimePicker in the shapes you actually ship: a date-only field, a time-only field, a full date+time field, a 12-hour field with spin buttons, and a min/max-constrained field - all in one form. Each is a masked text input (type OR pick) with a portalled dropdown; the calendar animates. The same component the grid mounts to edit a datetime cell.
Imports, features and API used
Imports: @svgrid/grid
Frequently asked questions
How do I make a date-only field?
Set dropDownDisplayMode='calendar' and a date formatString such as yyyy-MM-dd. The clock tab disappears and the value's time part stays at midnight; 'time' gives the opposite, a clock-only field.
How do I constrain the range?
Pass min and max as Dates. Typing a value outside them reverts, and the calendar disables days outside the bounds.
What do the spin buttons do?
spinButtons adds up and down arrows to the input that step the focused segment, hour, minute or day, without opening the dropdown.
Related documentation
Related articles
- A Date-Picker Cell Editor in SvGrid - How to make date columns editable with a real date picker in SvGrid - including display formatting, time zone handling, and validation that preserves user input.
- Immutable Grid Updates Without Killing Performance - Surgical immutability - how to get predictable reactivity in SvGrid without the cost of cloning everything on every change.
- Column Definitions in SvGrid - Fields, Accessors, and Formatting - A practical look at how ColumnDef controls field binding, value resolution, sort behavior, and custom cell rendering in SvGrid.
Source code (259-datetimepicker-forms.svelte)
<script lang="ts">
/**
* SvDateTimePicker in the shapes you actually ship: a date-only field, a
* time-only field, a full date+time field, a 12-hour field with spin buttons,
* and a min/max-constrained field - all in one form. Each is a masked text
* input (type OR pick) with a portalled dropdown; the calendar animates.
* The same component the grid mounts to edit a `datetime` cell.
*/
import { SvDateTimePicker } from '@svgrid/grid'
const now = new Date()
const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate())
const in90 = new Date(+todayStart + 90 * 86400000)
let date = $state<Date | null>(todayStart)
let time = $state<Date | null>(new Date(now.getFullYear(), now.getMonth(), now.getDate(), 9, 30))
let dateTime = $state<Date | null>(now)
let meeting = $state<Date | null>(null)
let booking = $state<Date | null>(null)
const long = new Intl.DateTimeFormat(undefined, { dateStyle: 'full', timeStyle: 'short' })
const show = (d: Date | null) => (d ? long.format(d) : '-')
const fields = $derived([
['Date only', date],
['Time only', time],
['Date + time', dateTime],
['12-hour + spinners', meeting],
['Constrained (next 90 days)', booking],
] as const)
</script>
<div class="wrap">
<header>
<h2>Date-time picker - form fields</h2>
<p>
<code>SvDateTimePicker</code> = a masked input plus a portalled DATE / TIME dropdown.
Type a value or pick it; bad input reverts. Below: five common configurations. The dropdown
calendar uses <code>animate</code>, so navigating months slides.
</p>
</header>
<div class="grid">
<form class="card">
<label>
<span>Date only <em>(calendar tab only)</em></span>
<SvDateTimePicker
value={date}
dropDownDisplayMode="calendar"
formatString="yyyy-MM-dd"
placeholder="Pick a date"
animate="slide"
onChange={(v) => (date = v)}
/>
</label>
<label>
<span>Time only <em>(clock tab only)</em></span>
<SvDateTimePicker
value={time}
dropDownDisplayMode="time"
formatString="HH:mm"
placeholder="Pick a time"
onChange={(v) => (time = v)}
/>
</label>
<label>
<span>Date + time <em>(both tabs)</em></span>
<SvDateTimePicker
value={dateTime}
formatString="yyyy-MM-dd HH:mm"
placeholder="When?"
animate="slide"
weekNumbers
onChange={(v) => (dateTime = v)}
/>
</label>
<label>
<span>12-hour + spin buttons <em>(arrow-key / button steps)</em></span>
<SvDateTimePicker
value={meeting}
formatString="MM/dd/yyyy hh:mm a"
hourFormat="12-hour"
minuteInterval={5}
spinButtons
stepMinutes={15}
placeholder="MM/DD/YYYY hh:mm AM"
animate="slide"
onChange={(v) => (meeting = v)}
/>
</label>
<label>
<span>Constrained <em>(today → +90 days)</em></span>
<SvDateTimePicker
value={booking}
min={todayStart}
max={in90}
firstDayOfWeek={1}
formatString="yyyy-MM-dd HH:mm"
placeholder="Within 90 days"
animate="slide"
onChange={(v) => (booking = v)}
/>
</label>
</form>
<aside class="readout">
<h3>Values</h3>
<dl>
{#each fields as [label, val] (label)}
<dt>{label}</dt>
<dd class:empty={!val}>{show(val)}</dd>
{/each}
</dl>
<p class="hint">Constrained field: days outside the window are struck through and the typed value clamps in.</p>
</aside>
</div>
</div>
<style>
.wrap { padding: 20px; max-width: 940px; display: flex; flex-direction: column; gap: 16px; }
header h2 { margin: 0 0 4px; font-size: 20px; font-weight: 700; }
header p { margin: 0; color: var(--sg-muted, #64748b); font-size: 13.5px; line-height: 1.5; max-width: 680px; }
code { background: var(--sg-row-hover-bg, #eef2ff); padding: 1px 5px; border-radius: 5px; font-size: 12px; }
.grid { display: flex; gap: 28px; align-items: flex-start; flex-wrap: wrap; }
.card { display: flex; flex-direction: column; gap: 16px; min-width: 280px; }
.card label { display: flex; flex-direction: column; gap: 6px; }
.card label > span { font-size: 12.5px; font-weight: 650; color: var(--sg-fg, #0f172a); }
.card label em { font-weight: 400; font-style: normal; color: var(--sg-muted, #94a3b8); }
.readout { flex: 1; min-width: 240px; }
.readout h3 { margin: 0 0 10px; font-size: 13px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--sg-muted, #64748b); }
.readout dl { margin: 0; display: grid; grid-template-columns: 1fr; gap: 10px; }
.readout dt { font-size: 12px; font-weight: 650; color: var(--sg-muted, #64748b); }
.readout dd { margin: 2px 0 0; font-size: 14px; }
.readout dd.empty { color: var(--sg-muted, #94a3b8); font-style: italic; }
.readout .hint { margin-top: 16px; font-size: 12px; color: var(--sg-muted, #94a3b8); line-height: 1.5; }
</style>More Date & Time examples
- Calendar - SvCalendar: a themeable month/year/decade calendar with single / range / week / multi selection, min-max, restricted + important dates and week numbers. The same component SvGrid mounts to edit a date cell - and usable standalone in any SvGrid app.
- Time picker - SvTimePicker: an analog clock-dial picker with 12/24-hour, minute snapping and hour to minute auto-switch. Drag the hand or click a number. The SvGrid time cell editor, usable standalone in any SvGrid app.
- Date-time picker - SvDateTimePicker: a formatted input plus a portalled dropdown with DATE / TIME tabs (calendar + clock). Type a masked value or pick it; invalid input reverts. min/max, nullable, 12/24-hour, spin buttons. The SvGrid datetime cell editor, standalone in any SvGrid app.
- Date-range input - SvDateRangeInput: a compact start/end field that opens a two-month range calendar with one-click presets (Today, Last 7 days, ...). Composes the same headless range engine as SvCalendar, and carries the shared editor contract - label, hint, error validation, dir (RTL) and localizable messages.
- Calendar - range + presets - SvCalendar as a date-range picker: selectionMode="range" with a one-click presets rail (Today, Last 7 days, This month, Year to date...), animated month navigation and mouse-wheel scrolling. Presets resolve relative to today. Same component, no extra dependency.