V4 Release Notes and Upgrade Guide

Initialization

Previously, a calendar was initialized by calling the $().fullCalendar() jQuery method. FullCalendar resided in a single JavaScript file that needed to be included on the page before pageload.

Now, a calendar is initialized by instantiating a Calendar object and then calling its render method. Also, all functionality has been broken into plugins. You’ll need to use the plugin system for any and all views in addition to drag-n-drop functionality. See a full list of plugins »

If you want to use script tags and browser globals you can do something like this:

<link href='fullcalendar/core/main.css' rel='stylesheet' />
<link href='fullcalendar/daygrid/main.css' rel='stylesheet' />

<script src='fullcalendar/core/main.js'></script>
<script src='fullcalendar/daygrid/main.js'></script>
<script>

  document.addEventListener('DOMContentLoaded', function() {
    var calendarEl = document.getElementById('calendar');

    var calendar = new FullCalendar.Calendar(calendarEl, {
      plugins: [ 'dayGrid' ],
      defaultView: 'dayGridMonth'
    });

    calendar.render();
  });

</script>

Or if you want to use an ES6 build environment install the necessary dependencies:

npm install --save @fullcalendar/core @fullcalendar/daygrid

And then write your JS:

import { Calendar } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';

document.addEventListener('DOMContentLoaded', function() {
  var calendarEl = document.getElementById('calendar');

  var calendar = new Calendar(calendarEl, {
    plugins: [ dayGridPlugin ],
    defaultView: 'dayGridMonth'
  });

  calendar.render();
});

You’ll need to manually include the necessary CSS files on your page like so:

<link href='node_modules/@fullcalendar/core/main.css' rel='stylesheet' />
<link href='node_modules/@fullcalendar/daygrid/main.css' rel='stylesheet' />

Also, many of the views have been renamed:

  • month renamed to dayGridMonth (requires the daygrid plugin, but has its own article)
  • basicWeek renamed to dayGridWeek (requires the daygrid plugin)
  • basicDay renamed to dayGridDay (requires the daygrid plugin)
  • agendaWeek renamed to timeGridWeek (requires the timegrid plugin)
  • agendaDay renamed to timeGridDay (requires the timegrid plugin)

Scheduler

The premium Scheduler product has been broken into a number of separate plugins. Also, the names and meanings of each view have changed.

Previously, to display a resource view, you would specify the resources option, and if working with vertical resource view, you might specify groupByResource or groupByDateAndResource as well. In v4, things are much more explicit. To display a resource view, you must choose one of the following views:

  • resourceTimeGridWeek - use instead of agendaWeek for resources (requires the resource-timegrid plugin)
  • resourceTimeGridDay - use instead of agendaDay for resources (requires the resource-timegrid plugin)
  • resourceDayGridWeek - use instead of basicWeek for resources (requires the resource-daygrid plugin)
  • resourceDayGridDay - use instead of basicDay for resources (requires the resource-daygrid plugin)
  • resourceTimelineYear - use instead of timelineYear for resources (requires the resource-timeline plugin)
  • resourceTimelineMonth - use instead of timelineMonth for resources (requires the resource-timeline plugin)
  • resourceTimelineWeek - use instead of timelineWeek for resources (requires the resource-timeline plugin)
  • resourceTimelineDay - use instead of timelineDay for resources (requires the resource-timeline plugin)

The following views previouly might have displayed resources, but in v4, they are guaranteed to NOT display resources:

  • timelineYear - will NOT display resources (requires the timeline plugin)
  • timelineMonth - will NOT display resources (requires the timeline plugin)
  • timelineWeek - will NOT display resources (requires the timeline plugin)
  • timelineDay - will NOT display resources (requires the timeline plugin)

Core Changes

print stylesheet

No need to use a separate <link> tag for a print-only stylesheet. It will be automatically included within the normal core/main.css, by use of media queries. Issue 3594

calling methods

Instead of using jQuery like $().fullCalendar('next'), do something like this:

calendar.next();
util functions

Top-level utility functions that were called like $.fullCalendar.formatDate() must now be accessed like import { formatDate } from '@fullcalendar/core' or via the global like FullCalendar.formatDate.

handlers

The this context will always be the Calendar object, as opposed to something arbitrary. Issue 2463 and 2699

var calendar = new Calendar(calendarEl, {
  select: function() {
    console.log(this === calendar); // true
  }
});
dynamic handlers

The on and off methods no longer accept namespaced event names like eventClick.namespace1.namespace2

dynamic options

Instead of using jQuery to get options like $().fullCalendar('option', 'optionName'), use getOption:

var optionValue = calendar.getOption('optionName');

And instead of using jQuery to set options like $().fullCalendar('option', 'optionName', 'optionValue'), use setOption:

calendar.setOption('optionName', 'optionValue');
getView method

To get the current View Object, access the Calendar’s view property instead. The getView() method has been removed.

render method

When called after initialization, will rerender everything, not just merely adjust the calendar’s size. For that, use updateSize. Issue 2709

loading method

No longer receives a view as its second parameter.

New things:

updateSize

Will readjust a calendar’s sizing (what the render method used to do).

batchRendering

Will group operations and consolidate them into a single rerender. Solves issue 3262

rerenderDelay

The amount of milliseconds to wait before rerendering anything on a calendar.

Date Library

Breaking changes:

Moment JS removal

Moment JS has been removed as a dependency and thus there is no need to include moment(.min).js. The API now deals in native Date objects as opposed to Moment objects. Related to issue 3937, 3672, 3672.

Ambiguously-timed Moments

Will now be Date objects with a time of 00:00:00. Callbacks nearly always provide an allDay boolean in addition. Issue 2981

date formatting strings

Instead of specifying date formats as command strings like MMMM d, YYYY, you specify them as objects like { month: 'long', day: 'numeric', year: 'numeric' }. This technique leverages the native DateTimeFormat which results in greater flexibility across locales and smaller locale files.

Also, you can use functions to programmatically generate date string text. Issue 3664

You can still use command strings, but you’ll need to use the moment or luxon plugins.

formatRange method

Signature has been changed from formatRange( moment1, moment2, formatString [, separator, isRTL ] ) to formatRange( date1, date2, settings ). Both date1 and date2 are Date object inputs and settings accepts formatting keys and other stuff too.

duration objects

Instead of Moment Duration objects, these objects are plain objects in the form { years, months, days, milliseconds }.

You can use the moment or luxon plugins to convert them to something more powerful.

weekNumberCalculation

When specifying a function, the function will receive a single Date object, not a Moment.

New things:

defaultRangeSeparator

Determines the separator text used for date-formatting ranges throughout the API, except for the toolbar title text, which is affected by titleRangeSeparator.

formatDate util func

Formats a date into a string.

formatDate method

Formats a date into a string. Inherits the locale and time zone settings of the calendar it’s called on.

formatIso method

Formats a date into an ISO8601 string. Outputs a UTC offset appropriate to the calendar it’s called on.

formatRange method

Formats two dates, a start and an end, into a string. Inherits settings from the calendar it’s called on.

Time Zone

timezone setting

Renamed to timeZone (to be more consistent with native naming conventions)

Date objects

The current timeZone will affect how you will interpret the Date objects emitted from the API. Whether you will use local methods like getHours() or UTC methods like getUTCHours().

Ambiguously-zoned Moments

Will now be Date objects in UTC. Issue 2981

the default time zone

The default timezone is now local. It used to be false, a technique that forced all dates into UTC, which has been removed…

a false time zone

The timezone: false technique is no longer available. Instead, use a named time zone like America/Chicago without any time zone plugins. Addresses 2981, 2780, 3951

Plugins

Browsers have a tough time supporting time zones other than local and UTC, which is why the default named time zone implementation essentially shoehorns everything into UTC Date objects. However you can use third-party adapter plugins like moment-timezone or luxon for more authentic time zone implementations, though browser support will vary. Issue 3188

Locales

Breaking changes:

paths to locale files

locale/*.js files have been moved to locales/*.js (added an s)

locale-all.js files has been moved to locales-all.js (added an s)

isRTL

Use the dir settings instead.

isRTL: true becomes dir: 'rtl'

dayNames

Removed. Use a date-formatting plugin or function instead.

dayNamesShort

Removed. Use a date-formatting plugin or function instead.

monthNames

Removed. Use a date-formatting plugin or function instead.

monthNamesShort

Removed. Use a date-formatting plugin or function instead.

jQuery UI Datepicker

Previously, FullCalendar was kind enough to populate locales for jQuery UI Datepicker. This is no longer the case.

Enhancements:

If you need a locale that does not have a matching locales/*.js file you may still set the locale setting. You will get partial support: most date-related strings within the calendar will correctly translate, but those in the buttons of the header/footer will not.

Event Model

Previously, event objects would be specified as plain objects, and then when accessing those same events in other parts of the API, they would be slightly-massaged versions of the same plain objects. Now, you still specify plain objects (though some properties have changed), but when you retrieve them in other parts of the API, they are instances of the Event class with methods for manipulation.

The plain-object’s input properties have changed a bit:

_id

_id can no longer be specified.

id

Was previously used to group related events together, so that they could be dragged/resized together. That is now done with groupId. The id properties should now be unique across all events in a calendar!

recurring props
(start/end/dow)

These props were never officially supported. Use startTime, endTime, and daysOfWeek instead. See simple event recurrence.

The outputted object, which is now an instance if the Event class, has properties that differ from the previously-available massaged plain-object:

_id

_id is no longer available. If you need a unique ID for each event, generate it yourself and put it in the id.

groupId

All events with the same groupId will be dragged, resized, and mutated together. Issue 4147

start

A Date object. No longer a moment.

end

A Date object. No longer a moment.

color

Access backgroundColor and borderColor instead. Color is an alias for setting both of these at the same time.

extendedProps

Previously, any non-standard properties would be preserved as top-level keys. Now, they are moved into the extendedProps hash.

It is also possible to specify an explicit extendedProps hash in the plain object. Issue 3228

resourceId

Removed. Use getResources instead, like event.getResources()[0].id

resourceIds

Removed. Use getResources instead, like event.getResources().map((resource) => resource.id)

Various methods of the Calendar object that manipulate events have been converted to Event methods:

clientEvents

Removed. For retrieving a single event, use getEventById. For retrieving all events, use getEvents. For retrieving a subset of events, filter the returned array:

var someEvents = calendar.getEvents().filter(function(event) {
  return event.title === 'My Event';
});
updateEvent

Removed. Instead, retrieve an Event object and then call a method that performs manipulation:

var event = calendar.getEventById('a');
event.setProp('title', 'new title');

Manipulation methods: setProp, setExtendedProp, setStart, setEnd, setDates, setAllDay, moveStart, moveEnd, moveDates

removeEvent

Removed. Instead, retrieve an Event object and then call its remove method:

var event = calendar.getEventById('a');
event.remove();
removeEvents

Removed. Instead, use multiple Event::remove calls. Group together for performance with batchRendering.

The following settings have changed:

defaultTimedEventDuration

The default has changed from 2 hours to 1 hour.

Also, recurring events is now a built-in feature! You can use simple event recurrence or use the RRule adapater. Issue 387

Event Source

Just as before, event sources can be specified in their “extended form”, a plain object with properties. The format for this plain object has changed slightly:

overlap

Can longer specify a function. Use the calendar-wide eventOverlap instead.

allow (new)

Like the calendar-wide eventAllow but for this event source only.

success (new)

A function that gets called when fetching succeeds. Will receive two arguments, the raw event array and an XHR if applicable. Can massage the response by returning an event source array to use instead.

failure (new)

A function that gets called when fetching failed. Probably because an AJAX request failed. Receives one argument, an error object.

eventDataTransform

Can now return false to exclude an event from being included. The calendar-wide eventDataTransform can do this too.

This plain object is then parsed and becomes available in places like getEventSourceById and the event object’s source property. Previously, these event source references would be slighly massaged version of the original plain object. Now, they are instances of the EventSource class and have methods that allow manipulation.

In v4, this new EventSource object is rather limited, offering only two properties: id and url. More info

Also, the EventSource object offers methods that replace the following Calendar methods:

refetchEventSources

Removed. Instead, retreive an Event Source object and then calls its refetch method:

var eventSource = calendar.getEventSourceById('a');
eventSource.refetch();
removeEventSource

Removed. Instead, retreive an Event Source object and then calls its remove method:

var eventSource = calendar.getEventSourceById('a');
eventSource.remove();
removeEventSources

Removed. Instead, use multiple EventSource::remove calls. Group together for performance with batchRendering.

There are two new calendar-wide callbacks:

eventSourceSuccess

A function that gets called when fetching succeeds. Will receive two arguments, the raw event array and an XHR if applicable. Can massage the response by returning an event source array to use instead. Issue 2431

eventSourceFailure

A function that gets called when fetching failed. Probably because an AJAX request failed. Receives one argument, an error object.

Event Source Function

An event-fetching function previously accepted the following arguments:

function( startMoment, endMoment, timeZoneStr, callback )

Now, it accepts the following arguments:

function( fetchInfo, successCallback, failureCallback )

It must call successCallback, failureCallback, or return a Promise. fetchInfo is an object that has a bunch of other properties. See the full article. A stubbed example of how to use the new signature:

var calendar = new Calendar(calendarEl, {
  events: function(fetchInfo, successCallback, failureCallback) {
    console.log(fetchInfo.startStr); // '2018-08-26T00:00:00-05:00'
    console.log(fetchInfo.endStr); // '2018-10-07T00:00:00-05:00'
    console.log(fetchInfo.timeZone); // 'local'
    successCallback([]);
  }
})

Solves issue 3593

Event JSON Feed

The following FullCalendar functionality has been affected:

JSONP requesting

It is no longer possible to request events via JSONP. CORS will be used instead. Make sure your server is set up to do CORS.

jQuery.ajax settings

The full range of jQuery.ajax settings are no longer accepted. However, can use the following new settings:

  • method - something like 'GET' (the default) or 'POST'
  • extraParams - will send GET/POST data to the server. the data property was previously used
  • success - Will receive two arguments, the raw event array and an XHR
  • failure - Receives one argument, an error object
cachebusting

The cache: false property is no longer available. Instead, adjust your script’s headers or use extraParams to insert your own cachebuster:

var calendar = new Calendar(calendarEl, {
  events: {
    url: '/myfeed.php',
    extraParams: function() {
      return {
        cachebuster: new Date().valueOf()
      };
    }
  }
});

The following request parameters have been affected:

startParam

Would previously generate strings like 2019-09-01 which did not have time parts or UTC offsets. Now, the string is guaranteed to have a time part (most likely 00:00:00) and will have a UTC offset that is dependant on the current timeZone. If the timeZone is set to 'local' and the user is localed in New York, the string might be 2019-09-01T00:00:00-05:00. Issue 3593

endParam

Same comments as startParam

timezoneParam

Renamed to timeZoneParam. Defaults to "timeZone" instead of "timezone".

If your server-side scripts previously relied on a timezone= GET/POST parameter, change it to timeZone instead!

Google Calendar Event Source

The Google Calendar Event Source has been affected:

googleCalendarError

Removed. Use eventSourceFailure instead. Issue 3982

timeZone

Previously, it was possible to specify timeZones with spaces such as “America/New York”. Now, you must use underscores like “America/New_York”.

View API

The way Views are customized and defined has been affected:

view-specific options

In parity with how view names have been renamed, instead of specifying agenda and basic to affect views of a certain type, use timeGrid and dayGrid respectively.

custom views written in JS

When subclassing the View class, the methods that must be implemented have changed quite a bit. More info.

registering a custom view

Previously, to globally define a new type of view, you would use this technique:

$.fullCalendar.views.specialView = {
  type: 'theViewType',
  defaults: { slotLabalInterval: '06:00' }
};

$.fullCalendar.views.customView = {
  'class': CustomViewClass
};

This must rewritten as a plugin:

import { createPlugin } from '@fullcalendar/core';

export default createPlugin({
  views: {
    specialView: {
      type: 'theViewType',
      slotLabalInterval: '06:00' // top-level property!
    },
    customView: CustomViewClass // can pass-in the class directly!
  }
})

Solves issue 3657.

The View object’s properties have changed a bit:

name

Renamed to type

intervalStart / intervalEnd

Renamed to currentStart / currentEnd. The current month/week/day/etc.

start / end

Renamed to activeStart / activeEnd. The date range that can be selected and accept events.

View Rendering

The following view-rendering-related callbacks have been affected:

viewRender

Renamed to datesRender. Parameters have changed.

viewDestroy

Renamed to datesDestroy. Parameters have changed.

viewSkeletonRender (new)

Triggered after a view’s non-date-related DOM structure has been rendered.

viewSkeletonDestroy (new)

Triggered before a view’s DOM skeleton is removed from the DOM.

Date Rendering

The following settings have been affected:

columnHeaderFormat

No longer accepts a format-string out of the box. Use a date-formatting object instead.

columnFormat

This deprecated alias of columnHeaderFormat has been removed. Use columnHeaderFormat instead.

slotLabelFormat

No longer accepts a format-string out of the box. Use a date-formatting object instead.

columnHeaderText

Accepts a normal Date object now.

dayRender

Instead of receiving ( date, el ), it now accepts an object. Stub example:

var calendar = new Calendar(calendarEl, {
  dayRender: function(info) {
    console.log(info.date.toISOString());
    console.log(info.el);
    console.log(info.view.type);
  }
});

Date Navigation

The getDate method will return a Date object not a Moment.

Date Clicking & Selecting

The interaction plugin is now required to detect date clicking and selecting:

import { Calendar } from '@fullcalendar/core';
import interactionPlugin from '@fullcalendar/interaction';

let calendar = new Calendar(calendarEl, {
  plugins: [ interactionPlugin ],
  selectable: true,
  select: function(info) { },
  dateClick: function(info) { }
});

Other breaking changes:

dayClick

Renamed to dateClick. Instead of ordered arguments, receives on object argument. Stub example:

var calendar = new Calendar(calendarEl, {
  dateClick: function(info) {
    console.log(info.date.toISOString());
    console.log(info.dateStr);
    console.log(info.allDay);
    console.log(info.dayEl);
    console.log(info.jsEvent);
  }
});

info.date is a Date object, not a Moment.

Also, this is now triggered when the user clicks on top of a background event. Issue 2843

select callback

Instead of ordered arguments, receives on object argument. Stub example:

var calendar = new Calendar(calendarEl, {
  select: function(info) {
    console.log(info.start.toISOString());
    console.log(info.end.toISOString());
    console.log(info.startStr + ' - ' + info.endStr);
    console.log(info.allDay);
  }
});

info.start and info.end are Date objects, not Moments.

select method

Removed the ordered argument signature: ( start, end, resourceId ). Instead, pass in a single object { start, end, resourceId }. The ordered argument signature ( start, end ) is still supported.

selectHelper

Renamed to selectMirror.

selectConstraint

A string that represents an event ID is no longer accepted. Instead, a string represents an event group ID. The simplest migration tactic is to assign groupId’s to your events with the same values as their id’s.

Also, a bug related to an unwanted unselect on touch devices has been fixed. Issue 4062

Event Rendering

The following settings have been affected:

nextDayThreshold

Default has been changed to 00:00:00. The previous default of 09:00:00 didn’t make a lot of sense. Issue 2902

Also, a bug with events that begin before the view’s start date has been fixed. Issue 3943

eventOrder

This value how has complete control over ordering events within a day, as opposed to before when events were always ordered by time first. The default is now 'start,-duration,allDay,title'. Issue 2907

If your old value for this setting was something like '-duration,title', you’ll want to include the start time in the value now. So, convert it to 'start,-duration,title'.

eventRender

Instead of accepting ( event, el, view ), it now accepts an object. Stub example:

var calendar = new Calendar(calendarEl, {
  eventRender: function(info) {
    console.log(info.event.title);
    console.log(info.el);
    console.log(info.view);
    console.log(info.isStart);
    console.log(info.isEnd);
    console.log(info.isMirror);
  }
});

Addresses issue 3674, 3956, 2616, 3952, and 3311

eventDestroy

Instead of accepting ( event, el, view ), it now accepts an object. Stub example:

var calendar = new Calendar(calendarEl, {
  eventDestroy: function(info) {
    console.log(info.event.title);
    console.log(info.el);
    console.log(info.view);
  }
});
timeFormat

Renamed to eventTimeFormat. Accepts a date-formatting object instead. Issue 1019

eventAfterRender

Renamed to eventPositioned. Instead of accepting ( event, el, view ), it now accepts an object.

eventAfterAllRender

Removed. The concecpt of event rendering being fully complete is flawed (such as when events are revealed in a +more popup). You should operate on individual events instead, via eventPositioned or use some other callback.

eventRenderWait

Removed. Use rerenderDelay instead, which waits before rerendering anything.

progressiveEventRendering (new)

When to render multiple asynchronous event sources in an individual or batched manner. Issue 1672 and 4072

The following Calendar methods have been affected:

renderEvent

Renamed to addEvent. The stick parameter has been removed in favor of a source parameter. When this source is fetched going forward, the dynamic event will be removed. Not specifying a source is equivalent to setting stick to true. So, by default, events will stick!

renderEvents

Removed. Use multiple addEvent calls instead. Group together for performance with batchRendering.

Visual changes:

In a timeGrid view (previously called “agenda view”, when an event is all-day, it would previously only render in the all-day area at the top. Now, it will render in both the all-day area and the time slots. See this illustration.

Event Clicking & Hovering

The following callbacks have been affected:

eventClick

Where previously received ordered arguments ( event, jsEvent, view ), will now receive a single object argument { event, el, jsEvent, view }. Now fires for background events. Issue 2808

You can no longer return false to cancel the browser’s navigation to the Event object’s URL. Instead, use the jsEvent:

var calendar = new Calendar(calendarEl, {
  eventClick: function(info) {
    info.jsEvent.preventDefault();
  }
});
eventMouseover

Renamed to eventMouseEnter. Where previously received ordered arguments ( event, jsEvent, view ), will now receive a single object argument { event, el, jsEvent, view }. Now fires for background events. Issue 3005

eventMouseout

Renamed to eventMouseLeave. Where previously received ordered arguments ( event, jsEvent, view ), will now receive a single object argument { event, el, jsEvent, view }. Now fires for background events. Issue 3005

Event Dragging & Resizing

The interaction plugin is now required to do event drag-n-drop and resizing:

import { Calendar } from '@fullcalendar/core';
import interactionPlugin from '@fullcalendar/interaction';

let calendar = new Calendar(calendarEl, {
  plugins: [ interactionPlugin ],
  editable: true
});

Other breaking changes:

eventDragStart

Where previously received ordered arguments ( event, jsEvent, ui, view ), now receives a single object { event, jsEvent, view }.

eventDragStop

Where previously received ordered arguments ( event, jsEvent, ui, view ), now receives a single object { event, jsEvent, view }.

eventDrop

Previously accepted ordered arguments ( event, delta, revertFunc, jsEvent, ui, view ). Now accepts an object:

var calendar = new Calendar(calendarEl, {
  eventDrop: function(info) {
    console.log(info.event);
    console.log(info.oldEvent); // data before the drop
    console.log(info.delta); // how far it was moved
    console.log(info.jsEvent);
    console.log(info.newResource); // if using a resource view
    console.log(info.oldResource); // if using a resource view

    if (confirm('revert change?')) {
      info.revert();
    }
  }
})

The delta property is a Duration object, no longer a Moment Duration. The oldEvent property is a new feature that allows you to inspect the event’s values prior to the mutation.

eventResizeStart

Where previously received ordered arguments ( event, jsEvent, ui, view ), now receives a single object { event, jsEvent, view }.

eventResizeStop

Where previously received ordered arguments ( event, jsEvent, ui, view ), now receives a single object { event, jsEvent, view }.

eventResize

Previously accepted ordered arguments ( event, delta, revertFunc, jsEvent, ui, view ). Now accepts an object:

var calendar = new Calendar(calendarEl, {
  eventResize: function(info) {
    console.log(info.event);
    console.log(info.prevEvent); // data before the drop
    console.log(info.startDelta); // how far start was moved
    console.log(info.endDelta); // how far end was moved
    console.log(info.jsEvent);

    if (confirm('revert change?')) {
      info.revert();
    }
  }
})

The startDelta is for resizing from start edge (with eventResizableFromStart). endDelta is for resizing from ending edge. Both are Duration objects, no longer Moment Durations. The prevEvent property is a new feature that allows you to inspect the event’s values prior to the mutation. Issue 4148

eventResizableFromStart (new)

Whether the event can be resized from its starting edge. Defaults to false. Issue 374

eventDragMinDistance (new)

How many pixels the user’s mouse/touch must move before an event drag or resize activates.

allDayMaintainDuration (new)

Determines how an event’s duration should be mutated when it is dragged from a timed section to an all-day section and vice versa. Issue 2764

dragScroll

Does auto-scrolling not just for event dragging, but also for event resizing, external element dragging, and date selecting. Issue 242

dragOpacity

Removed. Use the following CSS instead:

.fc-event.fc-dragging:not(.fc-selected) {
  opacity: .75;
}

You can tweak this CSS to get different opacity values for different scenarios.

eventConstraint
EventSource::constraint
Event::constraint

Can no longer specify a single string event ID, but rather a single string groupId that will match Event objects.

The recurring properties dow/start/end have been renamed to daysOfWeek/startTime/endTime.

Can accept an array of objects. Useful if you want to specify multiple date ranges.

Dragging External Elements & Events

Version 4 offers the following new features:

no third-party dependencies

You no longer need jQuery UI to be able to drag elements into a calendar. You can use the built-in Draggable API. More information. Issue 3902

plugins

If you’d like to use a third-party library for dragging such as Dragula, you can use the ThirdPartyDraggable API. More information. Will work for any other third party library.

dragging between calendars

It’s possible to drag events between two separate Calendar instances. More information. Issue 820

The following existing functionality has been affected:

data-event-* attributes

When associating event data with an element, you can no longer specify properties as separate HTML attributes. Instead, bundle them all together under one JSON string in the data-event attribute. Or better yet, just use the Draggable JS API.

data-event="1" attribute

You would previously specify a data-event="1" HTML attribute if you wanted to create an event upon drop, but did not have any other event-creation data to specify. This is now unnecessary because event creation happens by default.

start and time properties

External events that are dropped on all-day areas can be given a default time. This was previously done with the time/start properties. The proprty has been rename to startTime to be more consistent with naming elsewhere in the API. See External Event Dragging for more info.

event creation and
eventReceive callback

Event creation upon drop and firing of the eventReceive callback will happen by default. To prevent this from happening, specify { create: false } in your event data. More information.

The eventReceive callback previously received a single Event object argument. It now receives an object { event, draggedEl, view }. Also, it will now also be called when an event from another calendar has been dropped.

drop callback

Instead of ordered arguments ( date, jsEvent, ui, resourceId ) it will receive a single object { draggedEl, date, resource, allDay, jsEvent, view }. The date property is a Date object not a Moment. allDay is a boolean. resource is a Resource object if applicable.

If dropped on an all-day slot, the date property will always have a 00:00:00 time, regardless of the startTime in the event data, whereas previously the startTime would have been added.

Week Numbers

weekNumberTitle

Renamed to weekLabel. Will now affect week text in date formatting.

Event Popover

The following settings related to the event popover have been affected:

dayPopoverFormat

Does not accept date-formatting string by default. Use a date-formatting object.

navLinkDayClick

When specifying a function, accepts a Date object not a Moment.

Business Hours

When specifying business hours, the recurring properties dow / start / end have been renamed to daysOfWeek / startTime / endTime.

Toolbar

The following settings related to toolbars (aka, the header and footer) have been affected:

titleFormat

Does not accept date-formatting string by default. Use a date-formatting object.

titleRangeSeparator (new)

Determines the separator text when formatting the date range in the toolbar title. Default to an elongated dash.

Theming

theme setting

This previously-deprecated setting has been removed. Use themeSystem instead.

themeSystem set to 'bootstrap4'

Now, simply specify 'bootstrap'. Also, initializing a Bootstrap 4 theme requires additional steps.

Bootstrap 3 support

Removed. Consequently, the bootstrapGlyphicons option has been removed. Bootstrap 4 support remains however. Going forward, FullCalendar will only support the newest officially released version of Boostrap.

jQuery UI theme support

Removed. Consequently, the themeButtonIcons option has been removed.

Month View

The MonthView class is no longer exposed. Internally, the functionality has been rolled into DayGridView, which is exposed.

Agenda View

As mentioned above, the “agenda views” have been renamed to the timeGrid views. The following settings have been affected:

agendaEventMinHeight

Renamed to timeGridEventMinHeight

AgendaView class

Renamed to TimeGridView. Use this for programmatically extending functionality via a subclass.

List View

The following settings related to List View have been affected:

listDayFormat

Does not accept date-formatting string by default. Use a date-formatting object.

listDayAltFormat

Does not accept date-formatting string by default. Use a date-formatting object.

Timeline View

Breaking changes:

resourceColumns

The render function’s first argument is always a Resource object. Previously, it would vary depending on whether there was a field specified or not.

User-resizable columns and resource-area

The user is able to resize the resourceAreaWidth as well as the columns created by resourceColumns. Previously it “just worked,” but now you’ll need to load the interaction plugin.

Vertical Resource View

Previously, the groupByResource and groupByDateAndResource settings would do two things. They would “activate” a vertical resource view (as opposed to rendering the non-resource version of the view) as well as control the headers at the top of the view.

Now, explicitly specifying a resource view such as resourceTimeGridDay is how you “activate” a vertical resource. Additionally, these two settings have been collapsed into one:

datesAboveResources: false // the default. instead of groupByResource:true
datesAboveResources: true // instead of groupByDateAndResource:true

Resource Fetching

A resource-fetching function previously accepted the following arguments:

function( callback, startMoment, endMoment, timeZone )

Now, it acceps the following arguments:

function( fetchInfo, successCallback, failureCallback )

It must call successCallback, failureCallback, or return a Promise. fetchInfo is an object that contains the date-related properties. See the full article.

Other resource-fetching changes:

The following Calendar triggers have been affected:

resourcesSet

Removed. Was never officially supported.

Resource Model

Previously, resource objects would be specified as plain objects, and then when accessing those same events in other parts of the API, they would be slightly-massaged versions of the same plain objects. Now, you still specify plain objects, but when you retrieve them in other parts of the API, they are instances of the Resource class with methods for manipulation.

The following properties are now accepted in the raw object:

eventOverlap The eventOverlap setting for associated events. Does not accept a function.
eventConstraint The eventConstraint setting for associated events.
eventAllow The eventAllow setting for associated events.

The plain object will eventually be parsed into a proper Resource object, which has a number of differences from v3:

parent

Removed. Use getParent instead.

children

Removed. Use getChildren instead.

extendedProps

Where all non-standard properties are stored. Previously, non-standard properties would be stored in the top-level object.

The following resource-related methods/properties in the Calendar object have been affected:

eventResourceField

Removed. Use eventDataTransform instead.

addResource

The scrollTo argument is now true by default.

getResources

Now retrieves all resources, including nested child resources, in one flat array.

getTopLevelResources (new)

Retrieves only top-level resource (resources that don’t have a specified parent).

getResourceEvents

Removed. Use the Resource getEvents method instead.

removeResource

Removed. Use the Resource remove method instead.

Resource Rendering

resourceRender trigger

Used to accept ordered arguments ( resourceObj, labelTds, bodyTds ). Now accepts a single renderInfo object. The labelTds elements are now present in the renderInfo.el property as a single <td> element. If multiple elements are available for a single resource, resourceRender will be fired multiple times.

There is currently no way to retrieve the element(s) that were previously available in bodyTds. Issue 481

rerenderResources method

Previously rerendered all resources AND events. Now only renders the areas of the view where explicit resource data is displayed, such as the left cells in Timeline View and the top header in Vertical Resource View.

Versioning Scheme

Previously, the Core package was at version 3.x.x and the Scheduler package was at 1.x.x. There was no rhyme or reason as to which versions were compatible.

Now, all of v4’s plugins will be at 4.x.x including Scheduler functionality. All plugins with the same minor version (like 4.1.x) are implied to be compatible.

Package Managers

Support for NPM (and Yarn) is strong, but here’s what happened to support for other package managers:

Bower

Support has been dropped.

Composer

Support has been dropped. More info.