How can i add Preset Ranges in MUI 5 date range picker

Viewed 586

I am using MUI 5 date range picker my task is I need to add Preset Ranges in the place of the footer in the date range picker if any way we can do it so I need to add that in my MUI date picker if I click on that any range that date picker date will change accordingly when we select right now I don't have any idea how can I add certain range in MUI date picker

                ranges={{
                  Yesterday: [
                    moment().subtract(1, "day").startOf("day"),
                    moment().endOf("day"),
                  ],
                  Today: [
                    moment().startOf("day"),
                    moment().add(1, "day").endOf("day"),
                  ],
                  "Last Week": [
                    moment().subtract(1, "week").startOf("isoWeek"),
                    moment().subtract(1, "week").endOf("isoWeek"),
                  ],
                  "Last Month": [
                    moment().subtract(1, "month").startOf("month"),
                    moment().subtract(1, "month").endOf("month"),
                  ],
                  "This Month": [
                    moment().startOf("month"),
                    moment().endOf("month"),
                  ],
                  "Last Year": [
                    moment().subtract(1, "year").startOf("year"),
                    moment().subtract(1, "year").endOf("year"),
                  ],
                  "This Year": [
                    moment().startOf("year"),
                    moment().endOf("year"),
                  ],
                }}
export default function BasicDateRangePicker() {
  const [value, setValue] = React.useState([null, null]);

  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <DateRangePicker
        startText="Check-in"
        endText="Check-out"
        value={value}
        onChange={(newValue) => {
          setValue(newValue);
        }}
        renderInput={(startProps, endProps) => (
          <React.Fragment>
            <TextField {...startProps} />
            <Box sx={{ mx: 2 }}> to </Box>
            <TextField {...endProps} />
          </React.Fragment>
        )}
      />
    </LocalizationProvider>
  );
}

like this, if we can add

See image need output like this

2 Answers

Simply use the components prop of DateRangePicker and add buttons in Action container.

export function App() {
  const [value, setValue] = React.useState<DateRange<Date>>([null, null]);

  const handleClickOnToday = () => {
    setValue([
      moment().startOf("day").toDate(),
      moment().add(1, "day").endOf("day").toDate()
    ]);
  };

  const handleClickOnYesterday = () => {
    setValue([
      moment().subtract(1, "day").startOf("day").toDate(),
      moment().endOf("day").toDate()
    ]);
  };

  const handleClickOnLastWeek = () => {
    setValue([
      moment().subtract(1, "week").startOf("isoWeek").toDate(),
      moment().subtract(1, "week").endOf("isoWeek").toDate()
    ]);
  };

  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <DateRangePicker
        startText="Check-in"
        endText="Check-out"
        value={value}
        onChange={(newValue) => {
          setValue(newValue);
        }}
        components={{
          ActionBar: () => (
            <Stack spacing={2} p={1} direction="row">
              <Button onClick={handleClickOnToday} variant="outlined">
                Today
              </Button>
              <Button onClick={handleClickOnYesterday} variant="outlined">
                Yesterday
              </Button>
              <Button onClick={handleClickOnLastWeek} variant="outlined">
                Last Week
              </Button>
            </Stack>
          )
        }}
        renderInput={(startProps, endProps) => (
          <React.Fragment>
            <TextField {...startProps} />
            <Box sx={{ mx: 2 }}> to </Box>
            <TextField {...endProps} />
          </React.Fragment>
        )}
      />
    </LocalizationProvider>
  );
}

Here is the Codesandbox sample.

Add other buttons as you wish.

Copying the previous answer, i've just made an improvement - it creates all buttons and sets the selecions to the corresponding value inside ranges array:

interface IRangeProps {
  [key: string]: any;
}

const ranges: IRangeProps = {
  Yesterday: [
    moment().subtract(1, "day").startOf("day"),
    moment().endOf("day")
  ],
  Today: [moment().startOf("day"), moment().add(1, "day").endOf("day")],
  "Last Week": [
    moment().subtract(1, "week").startOf("isoWeek"),
    moment().subtract(1, "week").endOf("isoWeek")
  ],
  "Last Month": [
    moment().subtract(1, "month").startOf("month"),
    moment().subtract(1, "month").endOf("month")
  ],
  "This Month": [moment().startOf("month"), moment().endOf("month")],
  "Last Year": [
    moment().subtract(1, "year").startOf("year"),
    moment().subtract(1, "year").endOf("year")
  ],
  "This Year": [moment().startOf("year"), moment().endOf("year")]
};

export function App() {
  const [value, setValue] = React.useState<DateRange<Date>>([null, null]);

  const handleRangeclick = (rangeValue: DateRange<Date>) => {
    setValue(rangeValue);
  };

  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <DateRangePicker
        startText="Check-in"
        endText="Check-out"
        value={value}
        onChange={(newValue) => {
          setValue(newValue);
        }}
        components={{
          ActionBar: () => (
            <Stack spacing={2} p={1} direction="row">
              {Object.keys(ranges).map((key) => {
                return (
                  <Button
                    key={key}
                    onClick={() => handleRangeclick(ranges[key])}
                    variant="outlined"
                  >
                    {key}
                  </Button>
                );
              })}
            </Stack>
          )
        }}
        renderInput={(startProps, endProps) => (
          <React.Fragment>
            <TextField {...startProps} />
            <Box sx={{ mx: 2 }}> to </Box>
            <TextField {...endProps} />
          </React.Fragment>
        )}
      />
    </LocalizationProvider>
  );
}

export default App;

If that is what you want, i think @Adel Armand answer should be accepted as the right one, he did a great work and I just wanted to show a more automatic way.

Related