Web Component
FullCalendar comes as a Web Component (aka “Custom Element”). It provides a <full-calendar> tag that renders into its own shadow DOM and 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#
Via NPM#
The first step is to install the FullCalendar-related dependencies:
npm install --save @fullcalendar/web-component 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.
Then, write your JS:
// globally installs the <full-calendar> tag
import "@fullcalendar/web-component/global";
// plugins
import themePlugin from "@fullcalendar/web-component/themes/monarch"; // YOUR THEME
import dayGridPlugin from "@fullcalendar/web-component/daygrid";
// styles
import '@fullcalendar/web-component/skeleton.styles'; // ALWAYS NEED SKELETON
import '@fullcalendar/web-component/themes/monarch/theme.styles'; // YOUR THEME
import '@fullcalendar/web-component/themes/monarch/palettes/purple.css'; // YOUR THEME'S PALETTE
// initialize
const fullCalendarElement = document.querySelector('full-calendar')
fullCalendarElement.options = {
plugins: [themePlugin, dayGridPlugin]
} Then, in your HTML:
<full-calendar></full-calendar> Please note, skeleton.styles and theme.styles are JS modules, not stylesheets, and yes they do inject CSS. The calendar renders inside a shadow DOM, which a stylesheet on the page can’t reach. The element will throw an error if they are missing. Only the palette is a real .css file.
Customizing the Tag Name#
If you want a tag-name different that the default full-calendar, use this technique:
- import "@fullcalendar/web-component/global";
+ import { FullCalendarElement } from "@fullcalendar/web-component";
+ customElements.define("some-calendar-tag", FullCalendarElement); HTML:
<some-calendar-tag></some-calendar-tag> Via Script Tag#
Install with the following <script> and <link> tags:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- STANDARD JS -->
<script src="https://cdn.jsdelivr.net/npm/@fullcalendar/web-component@7.1.3/all/global.js"></script>
<!-- THEME JS -->
<script src='https://cdn.jsdelivr.net/npm/@fullcalendar/web-component@7.1.3/themes/monarch/global.js'></script>
<!-- STYLESHEETS -->
<script src='https://cdn.jsdelivr.net/npm/@fullcalendar/web-component@7.1.3/skeleton.styles.js'></script>
<script src='https://cdn.jsdelivr.net/npm/@fullcalendar/web-component@7.1.3/themes/monarch/theme.styles.js'></script>
<link href='https://cdn.jsdelivr.net/npm/@fullcalendar/web-component@7.1.3/themes/monarch/palettes/purple.css' rel='stylesheet' />
</head>
<body>
<full-calendar
options='{
"headerToolbar": {
"left": "prev,next today",
"center": "title",
"right": "dayGridMonth,dayGridWeek,dayGridDay"
}
}'
/>
</body>
</html> Please note, skeleton.styles.js and theme.styles.js are <script> tags, and yes they do inject CSS. This is required for the web component’s shadow DOM.
With globals there is no plugins array to write. The all/global.js file registers the following plugins for you:
interaction(for date selecting, event dragging & resizing)daygrid(for month and dayGrid views)timegrid(for timeGrid views)list(for list views)multimonth(for multi-month views)
The supplemental plugins are not in the bundle: Google Calendar, iCalendar, RRule, Moment formatting and Luxon formatting. Each ships its own global.js, which registers itself when loaded after all/global.js. Some also need their third-party library loaded first. See each plugin’s page for its script tags. They show the vanilla JS bundle, but the plugin’s global.js is the same for the Web Component.
Options#
The <full-calendar> element accepts all of FullCalendar’s options, in one of two ways.
The options attribute must be a valid JSON string. It’s convenient for writing a calendar entirely in HTML, but it can only hold data. It can’t hold functions, nor the plugins array.
The options property on the DOM element is a real JavaScript object, so it can hold anything:
const fullCalendarElement = document.querySelector("full-calendar");
fullCalendarElement.options = {
headerToolbar: {
left: "prev,next today",
center: "title",
right: "dayGridMonth,dayGridWeek,dayGridDay",
},
}; 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 is a function, so it must be given through the options property, not the attribute. For example, the dateClick handler is called whenever the user clicks on a date:
const fullCalendarElement = document.querySelector("full-calendar");
fullCalendarElement.options = {
plugins: [ /* ... */ ],
dateClick: function(info) {
alert(info.dateStr);
},
}; Modifying Options#
To change options after initialization, assign a new object to the options property. The calendar updates to match. This example toggles the weekends option:
const fullCalendarElement = document.querySelector("full-calendar");
fullCalendarElement.options = {
...fullCalendarElement.options,
weekends: !fullCalendarElement.options.weekends,
}; The element only reacts when the property is reassigned. Mutating the existing object in place will not trigger an update. Changing the options attribute has the same effect as reassigning the property.
Removing the element from the DOM destroys its calendar.
Content Injection#
There are many settings throughout the API for injecting custom content, like the eventContent event render hook. The Web Component accepts the same formats as vanilla JS: a string, HTML, DOM nodes, or a function returning any of those. See the vanilla JS instructions. Functions must be given through the options property.
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 option will set the initial date of the calendar, but to change it after that, you’ll need to rely on the date navigation methods.
Call the element’s getApi method:
const fullCalendarElement = document.querySelector("full-calendar");
const calendarApi = fullCalendarElement.getApi();
calendarApi.next(); getApi returns null until the element has been given options.
FullCalendar Premium#
How do you use FullCalendar Premium’s plugins with the Web Component? 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/web-component-scheduler Then, initialize your calendar. Make sure to include your schedulerLicenseKey:
// globally installs the <full-calendar> tag
import "@fullcalendar/web-component/global";
// plugins
import themePlugin from "@fullcalendar/web-component/themes/monarch";
import resourceTimelinePlugin from "@fullcalendar/web-component-scheduler/resource-timeline";
// stylesheets
import '@fullcalendar/web-component/skeleton.styles';
import '@fullcalendar/web-component/themes/monarch/theme.styles';
import '@fullcalendar/web-component/themes/monarch/palettes/purple.css';
// initialize
const fullCalendarElement = document.querySelector('full-calendar')
fullCalendarElement.options = {
schedulerLicenseKey: 'XXX',
plugins: [themePlugin, resourceTimelinePlugin],
initialView: 'resourceTimelineWeek'
} Premium via Script Tag#
Install with the following <script> and <link> tags:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!-- STANDARD + PREMIUM JS -->
<script src="https://cdn.jsdelivr.net/npm/@fullcalendar/web-component@7.1.3/all/global.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@fullcalendar/web-component-scheduler@7.1.3/all/global.js"></script>
<!-- THEME JS -->
<script src='https://cdn.jsdelivr.net/npm/@fullcalendar/web-component@7.1.3/themes/monarch/global.js'></script>
<!-- STYLESHEETS -->
<script src='https://cdn.jsdelivr.net/npm/@fullcalendar/web-component@7.1.3/skeleton.styles.js'></script>
<script src='https://cdn.jsdelivr.net/npm/@fullcalendar/web-component@7.1.3/themes/monarch/theme.styles.js'></script>
<link href='https://cdn.jsdelivr.net/npm/@fullcalendar/web-component@7.1.3/themes/monarch/palettes/purple.css' rel='stylesheet' />
</head>
<body>
<full-calendar
options='{
"headerToolbar": {
"left": "prev,next today",
"center": "title",
"right": "dayGridMonth,dayGridWeek,dayGridDay"
}
}'
/>
</body>
</html> Please note, skeleton.styles.js and theme.styles.js are <script> tags, and yes they do inject CSS. This is required for the web component’s shadow DOM.
TypeScript#
For @fullcalendar/web-component, nothing special is needed for TypeScript integration. Types are already included, including the FullCalendarElement class.