FlexDateRangeField stores an ordered pair of dates, optionally with local times. The panel maintains a draft until Apply; Cancel, Escape and an outside click discard that draft.
Basic period
The saved value is an array with start and end. An empty field saves null. The default day-only English label condenses dates, for example Oct 10 – 15, 2026. Custom formats and editable fields show both complete endpoints.
Default shortcuts
Without rangePresets(), the panel offers Today, Yesterday, Last 7 days, Last 30 days, This month, Last month, This quarter and Year to date. Last 7/30 days include Today; This month/quarter end at Today. Last month includes that entire previous month. These reporting periods use Gregorian dates.
Remove the shortcut panel
This removes the complete shortcut rail, including its mobile row. Calendar selection and Apply/Cancel remain available.
Your own periods
The list replaces the built-in shortcuts. Each item needs a nonempty label and valid ordered Y-m-d endpoints. Up to 30 custom presets are accepted. Presets do not bypass bounds or availability; Apply stays disabled for an invalid selection.
Dynamic periods
A PHP closure is evaluated when the field is rendered. To restore built-ins, use rangePresets(null). If a page stays open across midnight, refresh the field/page to refresh its reporting shortcuts.
One or two months
Small viewports always use the compact one-month layout, even if two months are requested. The preset rail becomes a scrolling row. On short screens the calendar body scrolls while confirmation controls remain reachable. Input values stay within the field width; the panel shows a complete summary.
Include start and end time
Clock controls share a row on desktop. On mobile their labels sit above each control, and the footer shows start and end on separate lines. All stored endpoints use the same storageFormat().
Date-only is the default. showSeconds() promotes an already timed range to second precision; it does not turn a day-only range into a timed one.
Available appointment hours
Both endpoints must use one of those times. minValue()/maxValue() can additionally bound the complete date/time period. Use disabledDates() and disabledWeekdays() to block endpoint days.
Range validation
Both endpoints must exist, be valid and meet the configured constraints. End cannot precede start. allowSameDay(false) requires different calendar days, including for timed ranges. Bounds are inclusive. Availability checks apply to endpoints; an unavailable day inside the period does not automatically invalidate it. Add a custom rule when every intervening day must be available.
Minimum number of days
Built-in date validation still applies alongside your rule. Use the configured storage format when parsing custom formats in your own rules.
Editable endpoints
Numeric segments follow your display format, including date/time segments when enabled. Arbitrary free text is not accepted as a date. An incomplete endpoint cannot submit successfully. On narrow inputs, scroll the segments or navigate them with the keyboard.
Clearing and inline selection
Ranges are not clearable by default. Inline ranges also require Apply to confirm a draft; Cancel restores the previous value. The range grid displays days belonging to each shown month; outsideDays() applies to single-date calendars rather than adding duplicate days to a range grid.
Appearance
The trigger uses the shared input appearance. The range panel expands from that trigger and returns to it on closing, including when the input label is clipped. Reduced-motion preferences remove the spring morph. See events to respond to confirmed changes. Last modified on October 16, 2026