Search code examples
react-datepicker

Switching between calendar and month picker in react-datepicker?


I need a date picker component for a React project, and after evaluating several candidate libraries it seems React Date Picker (react-datepicker) would match most requirements really well.

However, the project design says that when the user clicks the name of the month in the calendar view of the date picker, they should get a grid view of the months of the year for choosing one.

React Date Picker's built-in month picker is very close to the desired view and styling both that and the calendar is not a problem. But I don't think there's this kind of transition between different views/pickers implemented in RDP.

To illustrate the idea, I would basically need these views opened one at the time for the same input field:

enter image description here enter image description here

I know RDP's approach to the issue is having a separate month selector below the month name and I can of course try to sell that idea to my project's designer. But first I'd like to know if anyone can think of a simple way to do this – or better yet, knows of existing (MIT-licensed or similar) implementations.

I imagine I can build this by creating a custom header for the calendar component but writing the transition logic and a month picker from scratch seems quite laborious when RDP already has both of those views built in… And if I add both a calendar date picker and a month picker to the page and then toggle between them showing one while hiding the other, I believe they'll both have their own input fields also, leading to controlling the same data in two fields (which I would definitely want to avoid).


Solution

  • I imagine I can build this by creating a custom header for the calendar component […] And if I add both a calendar date picker and a month picker to the page and then toggle between them showing one while hiding the other, I believe they'll both have their own input fields also […]

    Well, this was the approach I decided to take in the end.

    Luckily our date picker design was rather simple so creating a custom header for the calendar wasn't hard, and showing and hiding the different pickers was rather easy using a simple React useState hook with a boolean value. Both of the pickers use another shared state hook for the date so they (at least seem to) stay nicely in sync.

    And toggling between the two hasn't caused any flickering to occur in any of the browsers I tested this in, so I'm quite happy with the end result.

    Update (09/2022):

    A brief example that works on the library's example site by just replacing whatever example there is with this. This isn't pretty or optimized but I hope it gives an idea how the logic works. (In this example the date/month picker type is changed each time a date is selected. In my actual implementation — that I have no access to anymore — this was controlled by a button in a custom header component.)

    () => {
      const [isMonthPicker, setMonthPicker] = useState(false);
      const [startDate, setStartDate] = useState(new Date());
      return (
        isMonthPicker ?
        <DatePicker
          selected={startDate}
          onChange={(date) => {
              setMonthPicker(false);
              setStartDate(date);
            }
          }
          dateFormat="MM/yyyy"
          showMonthYearPicker
          showFullMonthYearPicker
        />
        :
        <DatePicker
          selected={startDate}
          onChange={(date) => {
              setMonthPicker(true);
              setStartDate(date);
            }
          }
          dateFormat="MM/yyyy"
        />
      );
    };