Reputation: 179
MUI DatePicker shows a little arrow next to the year and month in the calendar. Clicking on it allows selecting a year. DateRangePicker, however, does not show that option in the calendar. How to enable year selection for date ranges that include many years? Scrolling through months to go 10 years back is not very comfortable. Thank you
Upvotes: 1
Views: 206
Reputation: 130521
I've tried challenging the same and after a too much wasted time, have decided to mimic the DateRangePicker
by combining my desired field component and an Popover
component which renders 2 date calendars components which at the end visually emulates the DateRangePicker
component, which was good enough for my needs.
Below is the basis of what I did (I am using tailwindcss & dateFns lib):
DateRangePicker
:import { useCallback, useMemo, useState } from "react";
import CalendarIcon from "@mui/icons-material/Event";
import { Popover, useTheme } from "@mui/material";
import { AdapterDateFns } from "@mui/x-date-pickers-pro/AdapterDateFnsV3";
import { LocalizationProvider } from "@mui/x-date-pickers-pro/LocalizationProvider";
import { SingleInputDateRangeField } from "@mui/x-date-pickers-pro/SingleInputDateRangeField";
import type { InputFieldSize } from "../sharedInputTypes";
import DateRangePickerDates from "./components/DateRangePickerDates/DateRangePickerDates";
const DateRangePicker = ({ value, onChange, size }) => {
const theme = useTheme();
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
const handleClick = useCallback((event: MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
}, []);
const handleClose = useCallback(() => {
setAnchorEl(null);
}, []);
return (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<SingleInputDateRangeField
value={value}
maxDate={new Date()}
onChange={onChange}
onClick={handleClick}
sx={sx}
slotProps={{
textField: {
InputProps: {
endAdornment: <CalendarIcon className="opacity-50" />,
},
},
}}
/>
<Popover
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
>
<DateRangePickerDates value={value} onChange={onChange} />
</Popover>
</LocalizationProvider>
);
};
export default DateRangePicker;
DateRangePickerDates
:import { FC, useCallback } from "react";
import { Divider } from "@mui/material";
import { DateCalendar } from "@mui/x-date-pickers/DateCalendar";
interface DateRangePickerDatesProps {
value: [Date | null, Date | null];
onChange: (value: [Date | null, Date | null]) => void;
}
const DateRangePickerDates: FC<DateRangePickerDatesProps> = ({
value,
onChange,
}) => {
const onCalendarChange = useCallback(
(newValue: Date | null, index: number) => {
if (!onChange || !value) return;
const newRange: [Date | null, Date | null] = [...value];
newRange[index] = newValue;
// Validate date range
if (newRange[0] && newRange[1]) {
if (index === 0 && newRange[0] > newRange[1]) {
newRange[1] = newRange[0];
} else if (index === 1 && newRange[1] < newRange[0]) {
newRange[0] = newRange[1];
}
}
onChange(newRange);
},
[onChange, value]
);
return (
<div className="flex">
<DateCalendar
format="system"
value={value?.[0]}
onChange={(v) => onCalendarChange(v, 0)}
/>
<Divider orientation="vertical" flexItem />
<DateCalendar
format="system"
value={value?.[1]}
onChange={(v) => onCalendarChange(v, 1)}
/>
</div>
);
};
export default DateRangePickerDates;
Upvotes: 0