Date Range Picker

Stable

Date 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

Select the start and end dates for the inspection
<!-- 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

Displays: Feb. 1, 2025 to Feb. 28, 2025
Displays: Feb. 14, 2025
<!-- 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

Clear button (X) appears when dates are selected
No clear button when required=True
<!-- 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

Choose your preferred date range
This field is required
Start date is required
End date must be after start date
<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>