Material-UI Fullcalendar
-Pro Component
Our Material-ui Fullcalendar is a full-sized drag & drop event
calendar.
Keep reading our Material-ui Fullcalendar examples and learn how to
use this plugin.
Usage
CSS
In order to use this plugin on your page you will need to import the
following styles inside your
index.js
:
Copy
import "@fullcalendar/common/main.min.css";
import "@fullcalendar/daygrid/main.min.css";
Example
Calendar
Copy
import React from "react";
// nodejs library that concatenates classes
import clsx from "clsx";
// JavaScript library that creates a callendar with events
import { Calendar } from "@fullcalendar/core";
import dayGridPlugin from "@fullcalendar/daygrid";
import interaction from "@fullcalendar/interaction";
// react component used to create sweet alerts
import ReactBSAlert from "react-bootstrap-sweetalert";
// @material-ui/core components
import { makeStyles } from "@material-ui/core/styles";
import Box from "@material-ui/core/Box";
import Button from "@material-ui/core/Button";
import Breadcrumbs from "@material-ui/core/Breadcrumbs";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import CardHeader from "@material-ui/core/CardHeader";
import Container from "@material-ui/core/Container";
import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import FilledInput from "@material-ui/core/FilledInput";
import FormGroup from "@material-ui/core/FormGroup";
import FormLabel from "@material-ui/core/FormLabel";
import Grid from "@material-ui/core/Grid";
import IconButton from "@material-ui/core/IconButton";
import Link from "@material-ui/core/Link";
import Slide from "@material-ui/core/Slide";
import Typography from "@material-ui/core/Typography";
// @material-ui/lab components
// @material-ui/icons components
import Check from "@material-ui/icons/Check";
import Home from "@material-ui/icons/Home";
import NavigateBefore from "@material-ui/icons/NavigateBefore";
import NavigateNext from "@material-ui/icons/NavigateNext";
// core components
import componentStyles from "assets/theme/views/admin/calendar.js";
import componentStylesButtons from "assets/theme/components/button.js";
const useStyles = makeStyles(componentStyles);
const useStylesButtons = makeStyles(componentStylesButtons);
const Transition = React.forwardRef(function Transition(props, ref) {
return <Slide direction="down" ref={ref} {...props} />;
});
let calendar;
let today = new Date();
let y = today.getFullYear();
let m = today.getMonth();
let d = today.getDate();
const eventsArray = [
{
id: 1,
title: "Call with Dave",
start: new Date(y, m, 1),
allDay: true,
className: "bg-red",
description:
"Nullam id dolor id nibh ultricies vehicula ut id elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
},
{
id: 2,
title: "Lunch meeting",
start: new Date(y, m, d - 1, 10, 30),
allDay: true,
className: "bg-orange",
description:
"Nullam id dolor id nibh ultricies vehicula ut id elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
},
{
id: 3,
title: "All day conference",
start: new Date(y, m, d + 7, 12, 0),
allDay: true,
className: "bg-green",
description:
"Nullam id dolor id nibh ultricies vehicula ut id elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
},
{
id: 4,
title: "Meeting with Mary",
start: new Date(y, m, d - 2),
allDay: true,
className: "bg-blue",
description:
"Nullam id dolor id nibh ultricies vehicula ut id elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
},
{
id: 5,
title: "Winter Hackaton",
start: new Date(y, m, d + 1, 19, 0),
allDay: true,
className: "bg-red",
description:
"Nullam id dolor id nibh ultricies vehicula ut id elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
},
{
id: 6,
title: "Digital event",
start: new Date(y, m, 21),
allDay: true,
className: "bg-warning",
description:
"Nullam id dolor id nibh ultricies vehicula ut id elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
},
{
id: 7,
title: "Marketing event",
start: new Date(y, m, 21),
allDay: true,
className: "bg-purple",
description:
"Nullam id dolor id nibh ultricies vehicula ut id elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
},
{
id: 8,
title: "Dinner with Family",
start: new Date(y, m, 19),
allDay: true,
className: "bg-red",
description:
"Nullam id dolor id nibh ultricies vehicula ut id elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
},
{
id: 9,
title: "Black Friday",
start: new Date(y, m, 23),
allDay: true,
className: "bg-blue",
description:
"Nullam id dolor id nibh ultricies vehicula ut id elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
},
{
id: 10,
title: "Cyber Week",
start: new Date(y, m, 2),
allDay: true,
className: "bg-yellow",
description:
"Nullam id dolor id nibh ultricies vehicula ut id elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
},
];
const CalendarView = () => {
const classes = { ...useStyles(), ...useStylesButtons() };
const [events, setEvents] = React.useState(eventsArray);
const [alert, setAlert] = React.useState(null);
const [modalAdd, setModalAdd] = React.useState(false);
const [modalChange, setModalChange] = React.useState(false);
const [startDate, setStartDate] = React.useState(null);
const [endDate, setEndDate] = React.useState(null);
const [radios, setRadios] = React.useState(null);
const [eventId, setEventId] = React.useState(null);
const [eventTitle, setEventTitle] = React.useState("");
const [eventDescription, setEventDescription] = React.useState("");
// eslint-disable-next-line
const [event, setEvent] = React.useState(null);
const [currentDate, setCurrentDate] = React.useState(null);
const calendarRef = React.useRef(null);
React.useEffect(() => {
createCalendar();
// eslint-disable-next-line
}, []);
const createCalendar = () => {
calendar = new Calendar(calendarRef.current, {
plugins: [interaction, dayGridPlugin],
initialView: "dayGridMonth",
selectable: true,
editable: true,
events: events,
headerToolbar: "",
// Add new event
select: (info) => {
setModalAdd(true);
setStartDate(info.startStr);
setEndDate(info.endStr);
setRadios("bg-info");
},
// Edit calendar event action
eventClick: ({ event }) => {
setEventId(event.id);
setEventTitle(event.title);
setEventDescription(event.extendedProps.description);
setRadios("bg-info");
setEvent(event);
setModalChange(true);
},
});
calendar.render();
setCurrentDate(calendar.view.title);
};
const changeView = (newView) => {
calendar.changeView(newView);
setCurrentDate(calendar.view.title);
};
const addNewEvent = () => {
var newEvents = events;
newEvents.push({
title: eventTitle,
start: startDate,
end: endDate,
className: radios,
id: events[events.length - 1] + 1,
});
calendar.addEvent({
title: eventTitle,
start: startDate,
end: endDate,
className: radios,
id: events[events.length - 1] + 1,
});
setModalAdd(false);
setEvents(newEvents);
setStartDate(undefined);
setEndDate(undefined);
setRadios("bg-info");
setEventTitle("");
};
const changeEvent = () => {
var newEvents = events.map((prop) => {
if (prop.id + "" === eventId + "") {
setEvent(undefined);
calendar.getEventById(eventId).remove();
let saveNewEvent = {
...prop,
title: eventTitle,
className: radios,
description: eventDescription,
};
calendar.addEvent(saveNewEvent);
return {
...prop,
title: eventTitle,
className: radios,
description: eventDescription,
};
} else {
return prop;
}
});
setModalChange(false);
setEvents(newEvents);
setRadios("bg-info");
setEventTitle("");
setEventDescription("");
setEventId(undefined);
setEvent(undefined);
};
const deleteEventSweetAlert = () => {
const styles = { display: "block", marginTop: "-100px" };
setAlert(
<ReactBSAlert
warning
style={styles}
title="Are you sure?"
onConfirm={() => {
setAlert(false);
setRadios("bg-info");
setEventTitle("");
setEventDescription("");
setEventId(undefined);
}}
onCancel={() => deleteEvent()}
confirmBtnCssClass="btn-secondary"
cancelBtnBsStyle="danger"
confirmBtnText="Cancel"
cancelBtnText="Yes, delete it"
showCancel
btnSize=""
>
You won't be able to revert this!
</ReactBSAlert>
);
};
const deleteEvent = () => {
event.remove();
var newEvents = events.filter((prop) => prop.id + "" !== eventId);
setEvent(undefined);
const styles = { display: "block", marginTop: "-100px" };
setAlert(
<ReactBSAlert
success
style={styles}
title="Success"
onConfirm={() => setAlert(null)}
onCancel={() => setAlert(null)}
confirmBtnBsStyle="primary"
confirmBtnText="Ok"
btnSize=""
>
Event deleted!
</ReactBSAlert>
);
setModalChange(false);
setEvents(newEvents);
setRadios("bg-info");
setEventTitle("");
setEventDescription("");
setEventId(undefined);
setEvent(undefined);
};
const containerRootClasses = { root: classes.containerRoot }
const breadcrumbsClasses = {
root: classes.breadcrumbRoot,
li: classes.breadcrumbLi,
ol: classes.breadcrumbOl,
separator: classes.breadcrumbSeparator,
}
const buttonContainedInfo = {
root: clsx(
classes.buttonContainedInfo,
classes.radioButton
),
};
const buttonContainedWarning = {
root: clsx(
classes.buttonContainedWarning,
classes.radioButton
),
};
const buttonContainedPrimary = {
root: clsx(
classes.buttonContainedPrimary,
classes.radioButton
),
};
const buttonContainedError = {
root: clsx(
classes.buttonContainedError,
classes.radioButton
),
};
const buttonContainedDefault = {
root: clsx(
classes.buttonContainedDefault,
classes.radioButton
),
};
const buttonContainedSuccess = {
root: clsx(
classes.buttonContainedSuccess,
classes.radioButton
),
};
const buttonContainedErrorSimple = {
root: classes.buttonContainedError,
}
const typographyProps = {
component: Box,
marginBottom: "0!important",
variant: "h3",
}
return (
<>
{alert}
<div className={classes.header}>
<Container
maxWidth={false}
component={Box}
classes={containerRootClasses}
>
<Grid
container
component={Box}
alignItems="center"
paddingTop="1.5rem"
paddingBottom="1.5rem"
>
<Grid item xs={12} lg={6}>
<Typography
variant="h2"
component="h6"
className={clsx(
classes.displayInlineBlock,
classes.mb0,
classes.textWhite
)}
>
{currentDate}
</Typography>
<Breadcrumbs
separator="-"
aria-label="breadcrumb"
classes={breadcrumbsClasses}
>
<Link
color="inherit"
href="/"
onClick={(e) => e.preventDefault()}
>
<Box
component={Home}
width="1.25rem!important"
height="1.25rem!important"
position="relative"
/>
</Link>
<Link
color="inherit"
href="/getting-started/installation/"
onClick={(e) => e.preventDefault()}
>
Calendar
</Link>
<Typography
component="span"
className={classes.breadcrumbActive}
>
{currentDate}
</Typography>
</Breadcrumbs>
</Grid>
<Grid item xs={12} lg={6} className={classes.textLgRight}>
<Button
variant="contained"
size="small"
className={classes.buttonRoot}
onClick={() => {
calendar.prev();
}}
>
<NavigateBefore />
</Button>
<Button
variant="contained"
size="small"
className={classes.buttonRoot}
onClick={() => {
calendar.next();
}}
>
<NavigateNext />
</Button>
<Button
variant="contained"
size="small"
className={classes.buttonRoot}
onClick={() => changeView("dayGridMonth")}
>
Month
</Button>
<Button
variant="contained"
size="small"
className={classes.buttonRoot}
onClick={() => changeView("dayGridWeek")}
>
Week
</Button>
<Button
variant="contained"
size="small"
className={classes.buttonRoot}
onClick={() => changeView("dayGridDay")}
>
Day
</Button>
</Grid>
</Grid>
</Container>
</div>
{/* Page content */}
<Container
maxWidth={false}
component={Box}
marginTop="-4.5rem"
classes={containerRootClasses}
>
<Grid container>
<Grid item xs={12}>
<Card elevation={0}>
<CardHeader
className={classes.cardHeader}
title="Calendar"
titleTypographyProps={typographyProps}
></CardHeader>
<CardContent className={classes.p0}>
<div
className="calendar"
data-toggle="calendar"
id="calendar"
ref={calendarRef}
/>
</CardContent>
</Card>
</Grid>
</Grid>
</Container>
<Dialog
open={modalChange}
TransitionComponent={Transition}
keepMounted
onClose={() => setModalChange(false)}
aria-labelledby="alert-dialog-slide-title"
aria-describedby="alert-dialog-slide-description"
>
<DialogContent>
<FormGroup>
<FormLabel>Event title</FormLabel>
<FilledInput
placeholder="Event Title"
type="text"
value={eventTitle}
onChange={(e) => setEventTitle(e.target.value)}
/>
</FormGroup>
<FormGroup>
<FormLabel>Status</FormLabel>
<Box>
<Box display="inline-block" marginRight=".5rem">
<IconButton
classes={buttonContainedInfo}
onClick={() => setRadios("bg-info")}
>
{radios === "bg-info" && (
<Box
width="1.25rem!important"
height="1.25rem!important"
component={Check}
/>
)}
</IconButton>
</Box>
<Box display="inline-block" marginRight=".5rem">
<IconButton
classes={buttonContainedWarning}
onClick={() => setRadios("bg-warning")}
>
{radios === "bg-warning" && (
<Box
width="1.25rem!important"
height="1.25rem!important"
component={Check}
/>
)}
</IconButton>
</Box>
<Box display="inline-block" marginRight=".5rem">
<IconButton
classes={buttonContainedError}
onClick={() => setRadios("bg-danger")}
>
{radios === "bg-danger" && (
<Box
width="1.25rem!important"
height="1.25rem!important"
component={Check}
/>
)}
</IconButton>
</Box>
<Box display="inline-block" marginRight=".5rem">
<IconButton
classes={buttonContainedSuccess}
onClick={() => setRadios("bg-success")}
>
{radios === "bg-success" && (
<Box
width="1.25rem!important"
height="1.25rem!important"
component={Check}
/>
)}
</IconButton>
</Box>
<Box display="inline-block" marginRight=".5rem">
<IconButton
color="default"
classes={buttonContainedDefault}
onClick={() => setRadios("bg-default")}
>
{radios === "bg-default" && (
<Box
width="1.25rem!important"
height="1.25rem!important"
component={Check}
/>
)}
</IconButton>
</Box>
<Box display="inline-block" marginRight=".5rem">
<IconButton
color="primary"
classes={buttonContainedPrimary}
onClick={() => setRadios("bg-primary")}
>
{radios === "bg-primary" && (
<Box
width="1.25rem!important"
height="1.25rem!important"
component={Check}
/>
)}
</IconButton>
</Box>
</Box>
</FormGroup>
<FormGroup>
<FormLabel>Description</FormLabel>
<FilledInput
placeholder="Event Desctiption"
type="text"
multiline
rows="4"
value={eventDescription}
onChange={(e) => setEventDescription(e.target.value)}
/>
</FormGroup>
</DialogContent>
<DialogActions>
<Box width="100%" display="flex" justifyContent="space-between">
<Box>
<Box display="inline-block" marginRight=".5rem">
<Button
color="primary"
variant="contained"
onClick={changeEvent}
>
Update
</Button>
</Box>
<Button
classes={buttonContainedErrorSimple}
variant="contained"
onClick={() => {
setModalChange(false);
deleteEventSweetAlert();
}}
>
Delete
</Button>
</Box>
<Button onClick={() => setModalChange(false)} color="primary">
Close
</Button>
</Box>
</DialogActions>
</Dialog>
<Dialog
open={modalAdd}
TransitionComponent={Transition}
keepMounted
onClose={() => setModalAdd(false)}
aria-labelledby="alert-dialog-slide-title"
aria-describedby="alert-dialog-slide-description"
>
<DialogContent>
<FormGroup>
<FormLabel>Event title</FormLabel>
<FilledInput
placeholder="Event Title"
type="text"
value={eventTitle}
onChange={(e) => setEventTitle(e.target.value)}
/>
</FormGroup>
<FormGroup>
<FormLabel>Status</FormLabel>
<Box>
<Box display="inline-block" marginRight=".5rem">
<IconButton
classes={buttonContainedInfo}
onClick={() => setRadios("bg-info")}
>
{radios === "bg-info" && (
<Box
width="1.25rem!important"
height="1.25rem!important"
component={Check}
/>
)}
</IconButton>
</Box>
<Box display="inline-block" marginRight=".5rem">
<IconButton
classes={buttonContainedWarning}
onClick={() => setRadios("bg-warning")}
>
{radios === "bg-warning" && (
<Box
width="1.25rem!important"
height="1.25rem!important"
component={Check}
/>
)}
</IconButton>
</Box>
<Box display="inline-block" marginRight=".5rem">
<IconButton
classes={buttonContainedError}
onClick={() => setRadios("bg-danger")}
>
{radios === "bg-danger" && (
<Box
width="1.25rem!important"
height="1.25rem!important"
component={Check}
/>
)}
</IconButton>
</Box>
<Box display="inline-block" marginRight=".5rem">
<IconButton
classes={buttonContainedSuccess}
onClick={() => setRadios("bg-success")}
>
{radios === "bg-success" && (
<Box
width="1.25rem!important"
height="1.25rem!important"
component={Check}
/>
)}
</IconButton>
</Box>
<Box display="inline-block" marginRight=".5rem">
<IconButton
color="default"
classes={buttonContainedDefault}
onClick={() => setRadios("bg-default")}
>
{radios === "bg-default" && (
<Box
width="1.25rem!important"
height="1.25rem!important"
component={Check}
/>
)}
</IconButton>
</Box>
<Box display="inline-block" marginRight=".5rem">
<IconButton
color="primary"
classes={buttonContainedPrimary}
onClick={() => setRadios("bg-primary")}
>
{radios === "bg-primary" && (
<Box
width="1.25rem!important"
height="1.25rem!important"
component={Check}
/>
)}
</IconButton>
</Box>
</Box>
</FormGroup>
<FormGroup>
<FormLabel>Description</FormLabel>
<FilledInput
placeholder="Event Desctiption"
type="text"
multiline
rows="4"
value={eventDescription}
onChange={(e) => setEventDescription(e.target.value)}
/>
</FormGroup>
</DialogContent>
<DialogActions>
<Box width="100%" display="flex" justifyContent="space-between">
<Box>
<Button color="primary" variant="contained" onClick={addNewEvent}>
Add event
</Button>
</Box>
<Button onClick={() => setModalAdd(false)} color="primary">
Close
</Button>
</Box>
</DialogActions>
</Dialog>
</>
);
};
export default CalendarView;
Props
Please refer to fullcalendar documentation.