OGE logoOGE

Date Editors

<oge-calendar> is a standalone month/year/decade calendar; <oge-date-box> puts it behind a field with locale-aware text parsing. Everything runs on native Date + Intl — no date library, no adapter, and all day math is local (never Date.parse), so values can't drift across timezones.

calendar date box Intl-only timezone-safe

Calendar

WAI-ARIA date grid with a roving-tabindex day: arrows move ±1/±7 days, PgUp/PgDn ±1 month (Shift ±1 year), Home/End week edges. The header drills out to year and decade views. min/max/disabledDates gate selection; week numbers follow a configurable rule.

roving tabindex min/max showWeekNumbers
SunMonTueWedThuFriSat
WeekMonTueWedThuFriSatSun
31
32
33
34
35
36
value: Sat Aug 15 2026

Date Box

The value is always a local Date | null — serialization is the app's concern. Typed text parses by the locale's own part order (dd/mm vs mm/dd) incl. month names; unparseable or out-of-range text shows the invalid state and reverts on blur — a wrong date is never committed. The popup follows the APG date-picker-dialog pattern: focus moves into the calendar, Esc returns it.

Date | null Intl parse blur revert
Not before Aug 10

Range selection

selectionMode: 'range' turns the calendar into a start–end picker with a live hover preview; viewsCount: 2 lays two months side by side. <oge-date-range-box> puts the same picker behind a single field with two parsed inputs — a reversed pair reorders on commit, either end may stay open. type: 'datetime' adds start/end time lists: day and time picks collect in a draft and commit together on OK.

selectionMode: range viewsCount oge-date-range-box type: datetime
MonTueWedThuFriSatSun
MonTueWedThuFriSatSun
period: Mon Aug 10 2026 → Thu Aug 20 2026
window: 8/14/2026, 10:00:00 PM → 8/15/2026, 6:30:00 AM

Time & datetime

type switches the editor: time shows a time picker (clock rail icon), datetime pairs it with the calendar — picking a date keeps the popup open for the time. timeView selects the picker layout: one interval list, or iOS-style hour + minute columns. applyValueMode: 'useButtons' collects picks in a draft and commits on OK.

type interval timeView applyValueMode

Grid integration

Grid and tree-list dataType: 'date' cells now edit through <oge-date-box> (compact sm shape) and the filter row applies a timezone-safe local day-range — [startOfDay, nextDay) for equality, day boundaries for ordering operators. Rows keep their storage shape: Date stays Date, yyyy-MM-dd strings round-trip as strings.

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { OgeColumn, OgeGrid } from '@oge-ui/grid';

@Component({
  selector: 'demo-root',
  imports: [OgeColumn, OgeGrid],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <!-- grid date editors and the filter row now run on <oge-date-box> -->
    <oge-grid [data]="rows" keyField="id" [filterRow]="true" [editing]="{ mode: 'cell' }">
      <oge-column field="shipped" dataType="date" />
    </oge-grid>
    <!-- filtering builds a timezone-safe local day-range: [startOfDay, nextDay) -->
  `,
})
export class Demo {
  protected readonly rows = [
    { id: 1, shipped: new Date(2026, 2, 11) },
    { id: 2, shipped: new Date(2026, 5, 2) },
  ];
}

Keyboard & accessibility

  • Calendar: role="grid" with real DOM focus on the day buttons (roving tabindex — deliberately not aria-activedescendant, per the APG date-picker-dialog pattern); aria-current="date" marks today.
  • Date box: ↓ opens the picker and hands focus to the calendar; Esc closes it and restores focus to the input, pressed again it reverts uncommitted text; Enter commits the typed text.
  • All texts (month/weekday names, aria labels, error messages) come from Intl + the localized OgeInputsMessages.