Custom Range View

The scheduler comes with built-in support for day, week and month views. For those situations where a custom range makes more sense, it is possible to override the calendar navigation component with a range picker.

The calendar header can be easily customized and a two-way synchronization needs to be kept between the scheduler and range picker.

Get started with this example

Demo

Loading the live demo

Preview in full screen

Configure the Scheduler with a custom date range view — let users pick any date span from a header range picker instead of fixed day.

Code

import {
  Button,
  CalendarNext,
  CalendarPrev,
  CalendarToday,
  Datepicker,
  Eventcalendar,
  formatDate,
  getJson,
  setOptions ,
} from '@mobiscroll/react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';

setOptions({
  locale:  ,
  theme: ' ',
  themeVariant: ' '
});

function App() {
  const [myEvents, setEvents] = useState([]);
  const [myRefDate, setMyRefDate] = useState();
  const [currentDate, setCurrentDate] = useState(new Date());
  const [rangeVal, setRangeVal] = useState([]);
  const [buttonText, setButtonText] = useState([]);
  const [calView, setCalView] = useState({
    scheduler: {
      type: 'day',
      size: 14,
    },
  });

  const startDate = useRef();
  const endDate = useRef();

  const buttonProps = useMemo(() => {
    const content = <span className="mbsc-calendar-title">{buttonText}</span>;
    return {
      children: content,
      className: 'mbsc-calendar-button',
      variant: 'flat',
    };
  }, [buttonText]);

  // Returns the number of days between two dates
  const getNrDays = useCallback(
    (start, end) => Math.round(Math.abs((end.setHours(0) - start.setHours(0)) / (24 * 60 * 60 * 1000))) + 1,
    [],
  );

  // Returns the formatted date
  const getFormattedRange = useCallback(
    (start, end) =>
      formatDate('MMM D, YYYY', new Date(start)) +
      (end && getNrDays(start, end) > 1 ? ' - ' + formatDate('MMM D, YYYY', new Date(end)) : ''),
    [getNrDays],
  );

  const handleChange = useCallback((args) => {
    const date = args.value;
    setRangeVal(date);
    if (date[0] && date[1]) {
      startDate.current = date[0];
      endDate.current = date[1];
    }
  }, []);

  const handleClose = useCallback(() => {
    if (startDate.current && endDate.current) {
      // Navigate the calendar
      setCurrentDate(startDate.current);
      // Set calendar view
      setMyRefDate(startDate.current);
      setCalView({
        scheduler: {
          type: 'day',
          size: getNrDays(startDate.current, endDate.current),
        },
      });
    }
    setRangeVal([startDate.current, endDate.current]);
  }, [getNrDays]);

  const handlePageLoading = useCallback(
    (args) => {
      const sDate = args.firstDay;
      const end = args.lastDay;
      const eDate = new Date(end.getFullYear(), end.getMonth(), end.getDate() - 1, 0);
      startDate.current = sDate;
      endDate.current = eDate;
      setTimeout(() => {
        // Set button text
        setButtonText(getFormattedRange(sDate, eDate));
        // Set range value
        setRangeVal([sDate, eDate]);
        // Navigate the calendar
        setCurrentDate(sDate);
      });
    },
    [getFormattedRange],
  );

  const handleSelectedDateChange = useCallback(
    (event) => {
      setCurrentDate(event.date);
    },
    [setCurrentDate],
  );

  useEffect(() => {
    getJson(
      'https://trial.mobiscroll.com/events/?vers=5',
      (events) => {
        setEvents(events);
      },
      'jsonp',
    );
  }, []);

  const customWithNavButtons = () => (
    <>
      <div>
        <Datepicker
          select="range"
          display="anchored"
          showOverlay={false}
          touchUi={true}
          buttons={[]}
          inputComponent={Button}
          inputProps={buttonProps}
          onClose={handleClose}
          onChange={handleChange}
          value={rangeVal}
        />
      </div>
      <div className="md-custom-range-view-controls">
        <CalendarPrev />
        <CalendarToday />
        <CalendarNext />
      </div>
    </>
  );

  return (
    <Eventcalendar
      clickToCreate={ }
      dragToCreate={ }
      dragToMove={ }
      dragToResize={ }
      eventDelete={ }
      selectedDate={currentDate}
      renderHeader={customWithNavButtons}
      view={calView}
      data={myEvents}
      onPageLoading={handlePageLoading}
      onSelectedDateChange={handleSelectedDateChange}
      refDate={myRefDate}
    />
  );
}

export default App;

Duplicate Session

You have signed in on a different machine. To keep everything in sync, you have been signed out of this session.

If you need to invite team members, manage seats and accounts you can do it from the licenses page.

Duplicate Session

We noticed you are logged in on a different machine and have closed your old session.

If you need to invite team members, manage seats and accounts you can do it from the licenses page.