Search code examples
reactjsfullcalendar

is there a way to use custom range?


Im trying to implement custom date range, is there any way to use ref api to do this? Im using custom toolbar component where I have next,today,prev buttons working with calendar ref, but I also want to have 2 date inputs, one is start date, second is end date, but unfortunately I cant figure out how to use ref to change calendar view dates

const CustomCalendarHeader: React.FC<Props> = ({
  calendarRef,
  currentDate,
  setCurrentDate,
}) => {
  const ref = calendarRef.current!.getApi();

  const nextHandle = () => {
    ref.next();
  };
  const prevHandle = () => {
    ref.prev();
  };
  const todayHandle = () => {
    ref.today();
  };
  const dayHandle = () => {
    ref.changeView('resourceTimelineDay');
  };
  const weekHandle = () => {
    ref.changeView('resourceTimelineWeek');
  };

  return (
    <Box
      sx={{
        display: 'flex',

        alignItems: 'center',
        justifyContent: 'space-between',
        px: 2,
        mb: 5,
      }}
    >
      <Box
        sx={{ display: 'flex', alignItems: 'center', gap: 2, flexGrow: 0.3 }}
      >
        <Button variant="contained" onClick={dayHandle}>
          Day
        </Button>
        <Button variant="contained" onClick={weekHandle}>
          Week
        </Button>

        <Typography>Custom: </Typography>
        <TextField type="date" size="small" sx={{ maxWidth: '125px' }} />
        -
        <TextField type="date" size="small" sx={{ maxWidth: '125px' }} />
       
      </Box>
      <ButtonGroup
        color="primary"
        variant="contained"
        sx={{ display: 'flex', alignItems: 'center' }}
      >
        <Button onClick={prevHandle}>Prev</Button>
        <Button onClick={todayHandle}>Today</Button>
        <Button onClick={nextHandle}>Next</Button>
      </ButtonGroup>
    </Box>
  );
};

and my Calendar component is looking like this:

<FullCalendar
                eventDrop={handleResizeOrRedropEvent}
                eventResize={handleResizeOrRedropEvent}
                droppable={true}
                eventReceive={handleEventReceive}
                viewDidMount={handleViewChange}
                ref={refCalendar as LegacyRef<FullCalendar> | undefined}
                nowIndicator
                dayMaxEvents
                timeZone="UTC"
                height="80vh"
                datesSet={(arg) => setCurrentDate(arg)}
                // visibleRange={{
                //   start: currentDate?.startStr,
                //   end: currentDate?.endStr,
                // }}
                displayEventTime={false}
                eventClick={handleEventClick}
                eventsSet={handleEvents}
                weekends={true}
                editable={true}
                selectable={true}
                // selectMirror={true}
                plugins={[resourceTimelinePlugin, interactionPlugin]}
                events={[dragEventRow, ...timeFrames]}
                resources={[dragEventRow, ...timeFrames].map((timeframe) => ({
                  id: `${timeframe.type}-${timeframe.title}`,
                  title: timeframe.title,
                  type: timeframe.type,
                  ...('children' in timeframe && {
                    children: timeframe.children,
                  }),
                }))}
                resourceGroupField="type"
                resourceAreaWidth={'20%'}
                initialView="resourceTimeline"
                eventContent={renderEventContent}
                headerToolbar={{
                  left: '',
                  center: 'title',
                  right: '',
                }}
              />
            )}

searched in docs, but only vound visibleRange that is not actually working for me alongside with datesSet, it causes infinite setState calls


Solution

  • Well, the answer is to use setOption as @ADyson mentioned, it will look like this one in my custom header:

    function to accept input`s changes:

    const handleDateRangeChange = () => {
        const startDate = (
          document.getElementById('start_date') as HTMLInputElement
        ).value;
        const endDate = (document.getElementById('end_date') as HTMLInputElement)
          .value;
    
        if (startDate && endDate) {
          ref.setOption('visibleRange', {
            start: startDate,
            end: endDate,
          });
        }
      };
    

    JSX of my custom range inputs:

              <Typography>Custom: </Typography>
              <TextField
                id="start_date"
                type="date"
                size="small"
                sx={{ maxWidth: '125px' }}
                onChange={handleDateRangeChange}
              />
              -
              <TextField
                id="end_date"
                type="date"
                size="small"
                sx={{ maxWidth: '125px' }}
                onChange={handleDateRangeChange}
              />