Building a Custom Date Range Picker in LWC
A practical guide to building a reusable date range picker component in Lightning Web Components, with accessible UX and clean API design.
Why build a custom date range picker?
Salesforce provides standard date inputs, but a lot of applications require selecting a range — think reports, dashboards, or activity filters. While third-party libraries can be used, a custom LWC gives you full control over UX, styling, and behavior.
Requirements
Here’s what we’re aiming for:
- Select start and end date
- Prevent invalid ranges
- Keyboard accessible
- Reusable and easy to integrate
Component structure
We’ll break the component into three parts: markup (HTML template), logic (JavaScript), and styles (CSS).
dateRangePicker/
├── dateRangePicker.html
├── dateRangePicker.js
├── dateRangePicker.js-meta.xml
└── dateRangePicker.css
Key implementation details
Some of the key parts worth highlighting:
- Using two
<lightning-input type="date">elements for start and end - Validating that end date is after start date
- Dispatching a custom event with the selected range
- Handling edge cases like clearing one of the dates
// dateRangePicker.js
import { LightningElement, api, track } from 'lwc';
export default class DateRangePicker extends LightningElement {
@track startDate = '';
@track endDate = '';
handleStartChange(event) {
this.startDate = event.detail.value;
this.validate();
}
handleEndChange(event) {
this.endDate = event.detail.value;
this.validate();
}
validate() {
if (this.startDate && this.endDate && this.endDate < this.startDate) {
this.template.querySelector('[data-id="end"]').setCustomValidity(
'End date must be after start date'
);
} else {
this.template.querySelector('[data-id="end"]').setCustomValidity('');
this.dispatchEvent(new CustomEvent('rangechange', {
detail: { start: this.startDate, end: this.endDate }
}));
}
this.template.querySelector('[data-id="end"]').reportValidity();
}
}
Conclusion
Building a custom date range picker in LWC is straightforward once you break it down. By keeping the API simple and the UX accessible, the component becomes easy to reuse across different parts of your application.