Custom Range View
Usage
theme="ios" You can turn auto theming on and let it decide based on the platform.
Usage
themeVariant="light" You can turn auto dark mode on based on system settings.
Usage
clickToCreate={true}
// click to create is on dragToCreate={true}
// drag to create is on dragToMove={true}
// reordering is on dragToResize={true}
// resizing is on eventDelete={true}
// deleting is on Fine-tune drag & drop with these options, which are false by default.
Usage
locale={localeEn} Selecting the locale loads the localized settings and the translated UI text.
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.
Demo

Code
View code on GitHub
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;
import {
Button,
CalendarNext,
CalendarPrev,
CalendarToday,
Datepicker,
Eventcalendar,
formatDate,
getJson,
MbscCalendarEvent,
MbscDatepickerChangeEvent,
MbscDatepickerValue,
MbscDateType,
MbscEventcalendarView,
MbscPageLoadingEvent,
MbscSelectedDateChangeEvent,
setOptions ,
} from '@mobiscroll/react';
import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
setOptions({
locale: ,
theme: ' ',
themeVariant: ' '
});
const App: FC = () => {
const [myEvents, setEvents] = useState<MbscCalendarEvent[]>([]);
const [myRefDate, setRefDate] = useState<MbscDateType>();
const [currentDate, setCurrentDate] = useState<MbscDateType>(new Date());
const [rangeVal, setRangeVal] = useState<MbscDatepickerValue>([]);
const [buttonText, setButtonText] = useState<string>();
const [calView, setCalView] = useState<MbscEventcalendarView>({
scheduler: {
type: 'day',
size: 14,
},
});
const startDate = useRef<Date>(null);
const endDate = useRef<Date>(null);
// Returns the number of days between two dates
const getNrDays = useCallback(
(start: Date, end: Date) => Math.round(Math.abs((new Date(end).setHours(0) - start.setHours(0)) / (24 * 60 * 60 * 1000))) + 1,
[],
);
// Returns the formatted date
const getFormattedRange = useCallback(
(start: Date, end: Date) =>
formatDate('MMM D, YYYY', new Date(start)) +
(end && getNrDays(start, end) > 1 ? ' - ' + formatDate('MMM D, YYYY', new Date(end)) : ''),
[getNrDays],
);
const onChange = useCallback((args: MbscDatepickerChangeEvent) => {
const date = args.value as Date[];
setRangeVal(date);
if (date[0] && date[1]) {
startDate.current = date[0];
endDate.current = date[1];
}
}, []);
const onClose = useCallback(() => {
if (startDate.current && endDate.current) {
// Navigate the calendar
setCurrentDate(startDate.current);
// Set calendar view
setRefDate(startDate.current);
setCalView({
scheduler: {
type: 'day',
size: getNrDays(startDate.current, endDate.current),
},
});
}
setRangeVal([startDate.current, endDate.current]);
}, [getNrDays]);
const handlePageLoading = useCallback(
(args: MbscPageLoadingEvent) => {
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: MbscSelectedDateChangeEvent) => {
setCurrentDate(event.date);
},
[setCurrentDate],
);
const buttonProps = useMemo(() => {
const content = <span className="mbsc-calendar-title">{buttonText}</span>;
return {
children: content,
className: 'mbsc-calendar-button',
variant: 'flat',
};
}, [buttonText]);
useEffect(() => {
getJson(
'https://trial.mobiscroll.com/events/?vers=5',
(events: MbscCalendarEvent[]) => {
setEvents(events);
},
'jsonp',
);
}, []);
const customWithNavButtons = () => (
<>
<div>
<Datepicker
select="range"
display="anchored"
showOverlay={false}
touchUi={true}
buttons={[]}
inputComponent={Button}
inputProps={buttonProps}
onClose={onClose}
onChange={onChange}
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;
.md-custom-range-view-controls {
display: flex;
flex: 1 0 auto;
justify-content: end;
align-items: center;
}