Repository navigation
14 Ful temporal inputs
The date/time family wraps the native date, time and datetime-local widgets, normalizing their string protocols, and adds two read-only display elements. All inputs are ful-inputs at heart: same slots, change events, readonly/required, input-* forwarding, Enter submits.
change fires once the value is committed, as on a text field: when the field is left or Enter is pressed, and at once for a value picked from the browser's picker. The native widgets fire their own change while the segments are typed (Chromium on every digit of the year), which a page reloading on change would act on with a year of 0002; the field does not pass those on, so a page never sees the dates a year passes through while it is typed. A value the page writes into a focused field is not an edit, so leaving the field afterwards fires no change for it.
A field left incomplete, a date missing its year for instance, reads as null, as the native control does: the browser exposes neither the segments typed nor anything but an empty value. Leaving it reports null like clearing it would, and a form submits it as empty. A required field then gets the server's problem for a missing value; an optional one is saved without it.

| Element | attribute / property value | widget |
|---|---|---|
ful-input-local-date |
YYYY-MM-DD |
date |
ful-input-local-time |
HH:MM / HH:MM:SS
|
time |
ful-input-instant |
UTC ISO-8601 in and out (2030-12-10T11:12:13.456Z) |
datetime-local |
The instant input's value is a UTC ISO-8601 string in and out, while the widget shows the local wall-clock equivalent; assignment and reading do the conversion. Feed it new Date().toISOString()-shaped strings, read the same back: no timezone arithmetic on your side.
The attributes of the three inputs are listed in the element reference under ful-input-local-date, ful-input-local-time and ful-input-instant. The value is null when the field is empty, and step is passed to the widget, in days here.
min/max accept an absolute YYYY-MM-DD, the literal now, or sign + amount + unit offsets from today:
| Example | Meaning |
|---|---|
min="2024-01-01" |
fixed bound |
min="now" |
today |
min="-18y" |
18 years ago |
max="+2m" |
two months ahead (month arithmetic, clamped: Jan 31 + 1m → Feb 28/29) |
min="-5d" |
five days ago |
Anything else is passed to the widget unchanged.
Same shape over HH:MM[:SS]. Offsets are from now and use h/m units, m being minutes here (min="-30m", max="+8h"), wrapping around midnight. A bound resolved from now or an offset is floored to the step grid (60 seconds when step is unset), so the values on the grid stay valid, and it carries seconds only when the step is not whole minutes. A literal bound is passed to the widget unchanged.
Same shape, ISO in/out. min/max take ISO instants (no now/offsets), and a date-only value is read as local midnight of that day. The change detail carries the ISO string.
Read-only formatters for when the value is text in a page, not a field:
<p>shipped on <ful-local-date>2030-12-10</ful-local-date>,
at <ful-instant>2030-12-10T11:12:13.456Z</ful-instant></p>-
ful-local-date:YYYY-MM-DDtext content becomes a localized numeric date. -
ful-instant: ISO text content becomes a local wall-clock date-time,hour12: false.
Both honor a locale attribute over the page locale, and show the default attribute's text when the content is blank or does not parse as a date, a day its month does not have (2024-02-30) included. A year below 100 is kept as it is written, not read as 19xx.
The inputs read no locale: the native widgets render in the user's language, and what fml localizes is the surrounding chrome (warnings and errors). Display elements resolve locale attribute → page locale → platform default.
ftl
httpc
ful
- Getting started
- Fields
- Forms
- Inputs
- Select
- Files
- Temporal inputs
- Tables
- Disclosures
- Navigation
- Async sections
- Timing and storage
- Theming
Extending
Reference
Project