Date Range Picker
StableDate range picker component with Alpine.js reactive state and hidden form inputs, integrated with Cally calendar web components for selecting date ranges.
API Reference
| Attribute | Description | Type | Default |
|---|---|---|---|
id
|
Unique identifier — auto-generated if not provided | string |
auto
|
label
|
Fieldset legend label shown above the component | string |
""
|
placeholder
|
Button text displayed when no dates are selected | string |
"Pick a date range"
|
start_date
|
Initial start date value (Python date object)
|
date | None |
None
|
end_date
|
Initial end date value (Python date object)
|
date | None |
None
|
required
|
When False, a clear button appears when dates are selected
|
boolean |
False
|
disabled
|
Disables the trigger button | boolean |
False
|
start_date_name
|
Name attribute for the hidden start date input | string |
"start_date"
|
end_date_name
|
Name attribute for the hidden end date input | string |
"end_date"
|
hx
|
HTMX attributes for the form wrapper — triggers server-side actions on date change | string |
""
|
hint
|
Helper text displayed below the component | string |
""
|
error
|
Single error message shown below the component | string |
""
|
errors
|
List of error messages (for Django form field errors) | list |
[]
|
Built-in behavior: the component manages Alpine.js reactive state internally, automatically updating the button label, hidden form inputs, and triggering form change events on selection.
Auto-close: the calendar popover closes automatically after a complete date range is selected.
Clear button: appears when dates are selected and required=False (default). Set :required=True to hide it.
Accessibility
Popover trigger: the trigger button uses popovertarget
to control the calendar popover, giving keyboard users full access (Tab to focus, Enter/Space to open, Escape to close).
Hidden inputs: two hidden <input type="hidden">
elements carry the start and end date values for form submission. Screen readers do not interact with
them directly.
Label: when the label prop is provided, the component
renders a <fieldset> with a <legend>,
giving the group an accessible name announced by screen readers.
Examples
Usage
<c-daterange-picker
label="Travel Dates"
placeholder="Choose travel dates"
start_date_name="travel_start"
end_date_name="travel_end">
</c-daterange-picker>
Basic Date Range Picker
<!-- Without label -->
<c-daterange-picker placeholder="Select date range"></c-daterange-picker>
<!-- With label -->
<c-daterange-picker
label="Travel Dates"
placeholder="Choose travel dates">
</c-daterange-picker>
<!-- With label and hint -->
<c-daterange-picker
label="Inspection Period"
placeholder="Pick inspection period"
hint="Select the start and end dates for the inspection">
</c-daterange-picker>
With Initial Values
<!-- In your Python view -->
<!-- from datetime import date -->
<!-- start = date(2025, 2, 1) -->
<!-- end = date(2025, 2, 14) -->
<c-daterange-picker
label="Pre-filled Range"
:start_date=start
:end_date=end
placeholder="Date range">
</c-daterange-picker>
Optional vs Required
<!-- Optional: shows clear (X) button when dates selected -->
<c-daterange-picker
label="Optional Date Range"
:required=False
:start_date=my_start_date
:end_date=my_end_date>
</c-daterange-picker>
<!-- Required: no clear button -->
<c-daterange-picker
label="Required Date Range"
:required=True
:start_date=my_start_date
:end_date=my_end_date>
</c-daterange-picker>
Custom Field Names
Hidden inputs will be named: vetting_start and vetting_end
<c-daterange-picker
label="Vetting period"
start_date_name="vetting_start"
end_date_name="vetting_end">
</c-daterange-picker>
<!-- Results in hidden inputs: -->
<input type="hidden" name="vetting_start" value="2025-02-01">
<input type="hidden" name="vetting_end" value="2025-02-14">
HTMX Integration
<c-daterange-picker
:start_date=inspection.start_date
:end_date=inspection.end_date
label="Inspection period"
start_date_name="inspection_start"
end_date_name="inspection_end"
hx="{% on 'change' 'save_inspection_dates' %}">
</c-daterange-picker>
Validation States
<c-daterange-picker
label="With Hint"
placeholder="Select dates"
hint="Choose your preferred date range">
</c-daterange-picker>
<c-daterange-picker
label="With Error"
placeholder="Select dates"
error="This field is required">
</c-daterange-picker>
<c-daterange-picker
label="With Multiple Errors"
placeholder="Select dates"
:errors="['Start date is required', 'End date must be after start date']">
</c-daterange-picker>
Disabled
<c-daterange-picker
label="Disabled Date Range"
:disabled=True
:start_date=my_start_date
:end_date=my_end_date
placeholder="Disabled date range">
</c-daterange-picker>