Vue Component

FullCalendar seamlessly integrates with the Vue JavaScript framework. It provides a component that 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:

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

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

npm install --save @fullcalendar/vue3 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 standard themes from themes.fullcalendar.io, 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 integrated with dark mode.

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

<script>
  import FullCalendar from "@fullcalendar/vue3";
  import themePlugin from "@fullcalendar/vue3/themes/monarch"; // YOUR THEME
  import dayGridPlugin from "@fullcalendar/vue3/daygrid";
  import interactionPlugin from "@fullcalendar/vue3/interaction";

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

  export default {
    components: {
      FullCalendar, // make the <FullCalendar> tag available
    },
    data() {
      return {
        calendarOptions: {
          plugins: [themePlugin, dayGridPlugin, interactionPlugin],
          initialView: "dayGridMonth",
        },
      };
    },
  };
</script>
<template>
  <FullCalendar :options="calendarOptions" />
</template>

Props and Emitted Events

Vue has the concept of “props” (via v-bind or :) versus “events” (via v-on or @). For the FullCalendar connector, there is no distinction between props and events. Everything is passed into the master options object as key-value pairs. Here is an example that demonstrates passing in an events array and a dateClick handler:

<script>
  import FullCalendar from "@fullcalendar/vue3";
  // ...

  export default {
    components: {
      FullCalendar, // make the <FullCalendar> tag available
    },
    data() {
      return {
        calendarOptions: {
          plugins: [ /* ... */ ],
          initialView: "dayGridMonth",
          dateClick: this.handleDateClick,
          events: [
            { title: "event 1", date: "2019-04-01" },
            { title: "event 2", date: "2019-04-02" },
          ],
        },
      };
    },
    methods: {
      handleDateClick: function (arg) {
        alert("date click! " + arg.dateStr);
      },
    },
  };
</script>
<template>
  <FullCalendar :options="calendarOptions" />
</template>

Modifying Options

You can modify your calendar’s options after initialization by reassigning them within the options object. This is an example of changing the weekends options:

<script>
  import FullCalendar from "@fullcalendar/vue3";
  // ...

  export default {
    components: {
      FullCalendar, // make the <FullCalendar> tag available
    },
    data() {
      return {
        calendarOptions: {
          plugins: [ /* ... */ ],
          initialView: "dayGridMonth",
          weekends: false, // initial value
        },
      };
    },
    methods: {
      toggleWeekends: function () {
        this.calendarOptions.weekends = !this.calendarOptions.weekends; // toggle the boolean!
      },
    },
  };
</script>
<template>
  <button @click="toggleWeekends">toggle weekends</button>
  <FullCalendar :options="calendarOptions" />
</template>

Slot Templates

Slot templates can be passed to FullCalendar components. They accepts slots for all content-injection settings such as eventContent.

<template>
  <FullCalendar :options="calendarOptions">
    <template v-slot:eventContent="arg">
      <b>{% raw %}{{{% endraw %} arg.event.title {% raw %}}}{% endraw %}</b>
    </template>
  </FullCalendar>
</template>

All slots are scoped slots that accept an argument (explicitly named arg in the above example).

Custom Toolbar Markup

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

<script>
  import FullCalendar, { useCalendarController } from "@fullcalendar/vue3";
  // ...

  export default {
    components: {
      FullCalendar, // make the <FullCalendar> tag available
    },
    data() {
      const controller = useCalendarController()
      const buttons = controller.getButtons()
      return {
        controller, // make available in markup
        buttons, // make available in markup
        calendarOptions: {
          controller, // give to calendar options
          plugins: [ /* ... */ ],
          initialView: "dayGridMonth",
        },
      };
    }
  };
</script>
<template>
  <div class='toolbar'>
    <button onClick={() => controller.today()}>{buttons.today.text}</button>
    <div class='toolbar-title'>{controller.view.title}</div>
  </div>
  <FullCalendar :options="calendarOptions" />
</template>

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

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”). In the template:

<FullCalendar ref="fullCalendar" :options="calendarOptions" />

Once you have the ref, you can get the underlying Calendar object via the getApi method:

let calendarApi = this.$refs.fullCalendar.getApi();
calendarApi.next();

Kebab-case in Markup

Some people prefer to write component names in kebab-case when writing markup. This will work fine:

<full-calendar :options="calendarOptions" />

However, the properties within calendarOptions must have the same names.

FullCalendar Premium

How do you use FullCalendar Premium’s plugins with Vue? 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/vue3-scheduler

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

<script>
  import FullCalendar from "@fullcalendar/vue3";
  import themePlugin from "@fullcalendar/vue3/themes/monarch";
  import resourceTimelinePlugin from "@fullcalendar/vue3-scheduler/resource-timeline";

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

  export default {
    components: {
      FullCalendar,
    },
    data() {
      return {
        calendarOptions: {
          plugins: [themePlugin, resourceTimelinePlugin],
          schedulerLicenseKey: "XXX",
        },
      };
    },
  };
</script>
<template>
  <FullCalendar :options="calendarOptions" />
</template>

TypeScript

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

Nuxt

If you plan to use the Nuxt Vue framework, you’ll need special configuration. See the example project