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:

import "@fullcalendar/common/main.min.css";
import "@fullcalendar/daygrid/main.min.css";

Example

Calendar
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.