Preact Component

FullCalendar for Preact is written in Preact itself rather than wrapped around the vanilla JS calendar. Everything it draws is a Preact element, so custom content is ordinary JSX rendered by your app’s own Preact. Its <FullCalendar> component exactly matches the functionality of FullCalendar’s standard API.

This package is released under an MIT license, the same license the standard version of FullCalendar uses. Useful links:

Installation#

This guide does not go into depth about initializing a Preact project. Please consult the aforementioned example/runnable projects for that.

The first step is to install the FullCalendar-related dependencies:

npm install --save @fullcalendar/preact temporal-polyfill

The temporal-polyfill package is small and tree-shakable, and can be used as a global polyfill if you explicitly opt-in (more info).

Next, choose one of the stock themes (see them live), along with a color palette. The examples below show a simplified way of importing the color palette (ex: purple.css), but please be aware, there are better ways to integrate with dark mode.

You may then begin to write a parent component that leverages the <FullCalendar> component:

import FullCalendar from "@fullcalendar/preact";
import themePlugin from "@fullcalendar/preact/themes/monarch"; // YOUR THEME
import dayGridPlugin from "@fullcalendar/preact/daygrid";

// stylesheets
import '@fullcalendar/preact/skeleton.css'; // ALWAYS NEED SKELETON
import '@fullcalendar/preact/themes/monarch/theme.css'; // YOUR THEME
import '@fullcalendar/preact/themes/monarch/palettes/purple.css'; // YOUR THEME'S PALETTE

export default function Calendar() {
  return (
    <FullCalendar
      plugins={[themePlugin, dayGridPlugin]}
      initialView="dayGridMonth"
    />
  );
}

You must initialize your calendar with at least one plugin that provides a view!

Props#

The <FullCalendar> component is equipped with all of FullCalendar’s options! Just pass them in as props. Example:

<FullCalendar
  plugins={[dayGridPlugin]}
  initialView="dayGridMonth"
  weekends={false}
  events={[
    { title: "event 1", date: "2019-04-01" },
    { title: "event 2", date: "2019-04-02" },
  ]}
/>

Props for the <FullCalendar> component are set the same way for both Class and Functional Components.

Options can also be scoped to a single view, or to a type of view, through the views option. See View-Specific Options.

Handlers#

A handler function can be passed into a Preact component and it will be called when something happens. For example, the dateClick handler is called whenever the user clicks on a date:

export default function Calendar() {
  const handleDateClick = (info) => {
    alert(info.dateStr);
  };

  return (
    <FullCalendar
      plugins={[ /* ... */ ]}
      dateClick={handleDateClick}
    />
  );
}

Modifying Props#

Props are reactive. When a prop’s value changes, the calendar updates to match. There is no need to call a method. This example toggles the weekends prop:

import { useState } from "preact/hooks";
import FullCalendar from "@fullcalendar/preact";
// ...

export default function Calendar() {
  const [weekends, setWeekends] = useState(false);

  return (
    <>
      <button onClick={() => setWeekends(!weekends)}>toggle weekends</button>
      <FullCalendar
        plugins={[ /* ... */ ]}
        weekends={weekends}
      />
    </>
  );
}

Be careful with values written inline, like an events array or a callback. They are new values on every render, so the calendar sees them as changed each time. Define them outside the component, or memoize them with useMemo and useCallback.

Content Injection#

There are many settings throughout the API for injecting custom content, like the eventContent event render hook. When you’re using the Preact implementation, these settings accept a function that returns JSX. The function receives a single argument, documented alongside each setting. For example, see eventContent’s argument.

export default function Calendar() {
  return (
    <FullCalendar
      plugins={[ /* ... */ ]}
      eventContent={renderEventContent}
    />
  );
}

function renderEventContent(eventInfo) {
  return (
    <>
      <b>{eventInfo.timeText}</b>
      <i>{eventInfo.event.title}</i>
    </>
  );
}

Custom Toolbar Markup#

You can completely customize the markup for the header or footer toolbars:

import FullCalendar, { useCalendarController } from "@fullcalendar/preact";
// ...

export default function Calendar() {
  const controller = useCalendarController();
  const buttons = controller.getButtonState();

  return (
    <div>
      <div className='toolbar'>
        <button onClick={() => controller.today()}>{buttons.today.text}</button>
        <div className='toolbar-title'>{controller.view.title}</div>
      </div>
      <FullCalendar
        controller={controller}
        plugins={[ /* ... */ ]}
      />
    </div>
  );
}

More generally, this “controller” technique allows you to use a calendar’s data outside the component itself. Learn about the CalendarController API →

Custom Views with Components#

It’s possible to make calendar views that have custom rendering logic. The Custom Views via JS article explains the general concept. When you’re using the Preact implementation, it’s possible to specify a Preact component. Example:

import FullCalendar, { sliceEvents } from "@fullcalendar/preact";
// ...

function CustomView(props) {
  const segs = sliceEvents(props, true); // allDay=true

  return (
    <>
      <div className="view-title">
        {props.dateProfile.currentRange.start.toUTCString()}
      </div>
      <div className="view-events">{segs.length} events</div>
    </>
  );
}

<FullCalendar
  views={{
    custom: CustomView
  }}
/>

Calendar API#

Hopefully you won’t need to do it often, but sometimes it’s useful to access the underlying Calendar object for raw data and methods.

This is especially useful for controlling the current date. The initialDate prop will set the initial date of the calendar, but to change it after that, you’ll need to rely on the date navigation methods.

To do something like this, you’ll need to get ahold of the component’s ref (short for “reference”). Once you do that, you call the getApi method of the “current” component instance:

import { useRef } from 'preact/hooks';
import FullCalendar from '@fullcalendar/preact'
// ...

export default function Calendar() {
  const calendarRef = useRef(null)

  function goNext() {
    const calendarApi = calendarRef.current.getApi()
    calendarApi.next()
  }

  return (
    <>
      <button onClick={goNext}>Go Next!</button>
      <FullCalendar
        ref={calendarRef}
        plugins={[ /* ... */ ]}
      />
    </>
  )
}

FullCalendar Premium#

How do you use FullCalendar Premium’s plugins with Preact? They are no different than any other plugin. Just follow the same instructions as you did dayGridPlugin in the above example. You’ll need an additional package however:

npm install --save @fullcalendar/preact-scheduler

Then, initialize your calendar. Make sure to include your schedulerLicenseKey:

import FullCalendar from "@fullcalendar/preact";
import themePlugin from "@fullcalendar/preact/themes/monarch";
import resourceTimelinePlugin from "@fullcalendar/preact-scheduler/resource-timeline";

// stylesheets
import '@fullcalendar/preact/skeleton.css';
import '@fullcalendar/preact/themes/monarch/theme.css';
import '@fullcalendar/preact/themes/monarch/palettes/purple.css';

export default function Calendar() {
  return (
    <FullCalendar
      schedulerLicenseKey="XXX"
      plugins={[themePlugin, resourceTimelinePlugin]}
    />
  );
}

TypeScript#

For @fullcalendar/preact, nothing special is needed for TypeScript integration. Types are already included.