Skip to content

UI editor: assist entry of FHIR temporal primitives (date, dateTime, time, instant) in the Guided form #549

Description

@smunini

Summary

The Guided form gives no help entering FHIR temporal primitives — date, dateTime, time, instant. Every one is a bare text box, so the user has to know the spec's format rules from memory and only finds out they got it wrong after a server round trip. Add authoring assistance for these types.

Spec reference: https://hl7.org/fhir/datatypes.html#primitive

Current behavior

crates/ui/templates/partials/editor-body.html:133-138 renders every primitive identically:

<input class="editor-row__input" type="text" value="{{ row.value }}" data-set="{{ row.path }}" >

No format hint, no placeholder, no picker, no client-side check. A malformed birthDate is caught only on blur, when the value round-trips to /ui/editor/render and comes back as a red row error.

Two things already in place that this can build on

1. The row already knows its FHIR type. Row.type_label is populated from the schema's type_ (crates/ui/src/editor.rs:446-449), so at render time the server knows a field is dateTime rather than just "a string". The template currently only prints it as a hint chip (editor-body.html:98-99). No new plumbing is needed to branch on type.

2. The authoritative format regex is already loaded. The validator carries the FHIR spec pattern per primitive on schema.regex and matches against it (crates/fhir-validator/src/engine/primitives.rs:41-49), compiled anchored as ^(?:…)$. That same pattern can drive a live client-side check and a generated format hint, instead of hand-copying regexes into the UI.

The design constraint — don't just drop in native pickers

Native HTML date inputs cannot represent what FHIR permits, and would silently destroy valid data:

Type FHIR permits Why the native control doesn't fit
date YYYY, YYYY-MM, or YYYY-MM-DD — partial precision is legal <input type="date"> can only express a full day
dateTime the three date forms, or a full timestamp; if a time is present a timezone offset is required <input type="datetime-local"> has no timezone, and can't do partials
instant always full precision with an offset (YYYY-MM-DDThh:mm:ss.sss+zz:zz) no native control produces this
time hh:mm:ss[.sss], no date, no timezone <input type="time"> commonly omits the seconds FHIR requires

So the input must stay free-text and authoritative, with assistance layered on top. There's a precedent in this same editor: the live $expand picker enriches a plain text input with a datalist via data-vs-url (editor-body.html:136, resources.js:126-172) without taking over the field. The same shape fits here.

Suggested direction

  • Per-type placeholder and format hint driven off type_label, stating what's allowed including partial precision.
  • Live format feedback using the schema regex already available server-side — flag a malformed value as you type rather than after a blur round trip.
  • An optional assist affordance that writes a conformant string: a picker, plus shortcuts like "today" / "now". Precision must be an explicit choice for date/dateTime, never silently upgraded from 2024 to 2024-01-01.
  • Timezone handling for dateTime and instant — default to the browser offset, allow Z or an explicit offset, and never emit a time without one.
  • Keep the typed value the source of truth so an existing partial date survives a visit to the field untouched.

Scope

In scope: date, dateTime, time, instant.

Out of scope but worth noting: the complex types built from these — Period (start/end are dateTime), Timing (event, repeat.bounds[x]), Age/Duration — pick up the benefit for free once the primitive rows improve, since their children render as ordinary rows. Also, the same "no assistance" gap applies to boolean, integer, unsignedInt, and positiveInt, which are likewise plain text boxes; if the mechanism generalizes cheaply, say so, but the ask here is the temporal types.

Acceptance criteria

  • date, dateTime, time, and instant rows show what format is expected before the user types.
  • Malformed values are flagged without waiting for a server round trip.
  • Partial-precision date and dateTime values can be entered and are preserved unchanged.
  • A dateTime/instant with a time always carries a timezone offset.
  • time values keep the required seconds component.
  • Existing values load, display, and survive an untouched visit to the field.
  • Works on /ui/editor and in the Resources edit modal (two separate JS implementations — see UI editor: Guided form is not usable for authoring a new resource (empty tree, picker and focus lost on every edit) #547).
  • Keyboard-accessible and labeled; a11y.spec.ts still passes.
  • Any user-facing text comes from the Fluent catalog (locales/{en,es,de}/main.ftl).
  • e2e coverage for entering each temporal type through the guided form.

Pointers

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions