The Oracle APEX blog is your source for APEX news, technical tips and strategic direction

Calendar Region Upgrade Guide in APEX 21.1

Daniel Hochleitner
Principal Member of Technical Staff

Blog Post Image

With the release of APEX 21.1, and beside other larger new features, also the Calendar Region got some attention and was updated. The main new features or changes are

  • Faceted Search integration

  • Declarative lazy loading option

  • Removed client side Google Calendar integration

  • Removed client side REST Webservice (JSON) integration

  • FullCalendar library updated to version 5 (5.5.1)

With the update of the underlying JavaScript library there are also larger changes under the hood in how FullCalendar functions.

Unlike previous versions, FullCalendar 5 isn't based on jQuery anymore, and moment.js - a well-known JavaScript date manipulation library - was removed as a dependency. Instead it's now written in pure JavaScript and also uses native date objects.

Thus these changes also have an impact on custom code developers might have written around the standard Calendar Region this posting should help to make things clearer and assist you with upgrading current calendars to the new version.


First of all let's talk about what didn't change

1. The end users experience!

At runtime the new version 5 calendar behaves and pretty much looks like the existing calendar (which used FullCalendar version 3). So things like drag & drop, keyboard navigation, different calendar views (like month, week, day or list) are still working as expected.

FullCalendar version 3

Version 3

FullCalendar version 5

Version 5


2. Existing calendars

If an environment was upgraded to APEX 21.1 or an existing older app was imported into an APEX 21.1 workspace, existing calendars won't be updated automatically and still use the older FullCalendar version 3 implementation. We decided to do that to not brake any existing apps or pages.


But how to upgrade to the new version?

There are 2 options to really upgrade the calendar to the new version and also use new functionality like Faceted Search integration or lazy loading capabilities:

  • Using the Application Upgrade wizard (under App > Utilities > Upgrade Application) to automatically upgrade existing Calendar Regions

The wizard will only show Calendar Regions which are good candidates for an automatic upgrade, meaning only calendars which don't use client side Google Calendar or REST Webservice (JSON) integration or using any JavaScript Initialization Code inside region attributes.

APEX Application Upgrade Wizard - highlighting Calendar Region entry

  • Manually upgrade a Calendar Region

If an app uses some removed features or any JavaScript customization the best way to upgrade existing Calendar Regions would be manually by hand. By providing a SQL statement like this it should be easy to identify those regions:

select page_id,
  from apex_application_page_regions
 where application_id   = 100 -- your APP_ID
   and source_type_code = 'NATIVE_CSS_CALENDAR' -- Calendar Region
   and attribute_23     = '3' -- old FullCalendar version 3
 order by page_id


Then the upgrade process itself is pretty simple. There's a new "Version" attribute on region level and by setting this to "FullCalendar 5" is enough to make use of the new functionality.

Calendar Region version attribute


Now let's have deeper look at adjusting deprecated features or advanced customization

If the old calendar used one of the removed features, such as client side Google Calendar or REST Webservice (JSON) integration, then this has to be resolved before updating the calendar to the new version, otherwise this page will not work properly anymore.

Luckily both features can easily be transformed to make use of APEX REST Data Sources instead of doing an HTTP request on the client browser.

The provided REST Data Sources can then be used as a Region Source instead of a SQL statement.

The deprecated REST Webservice (JSON) functionality should be straight forward, the Google Calendar API on the other hand needs additional information, such as an API Key and the calendar ID of a publicly shared calendar. The documentation could be found here.

The REST endpoint URL to include a public Google Calendar looks like this:

GET https://www.googleapis.com/calendar/v3/calendars/#PUBLIC_CALENDAR_ID#/events?key=#API_KEY#

A second way - without using declarative REST Data Sources - is using the APEX_DATA_PARSER API. A pretty unknown feature of it:

It also can parse calendar ICS files pretty well, so this would enable us to directly use the public iCal address of an Google calendar or any other calendar. A query to parse and get calendar's data could look like this:

select ics_data_t.col001 as ics_uid,
       ics_data_t.col002 as ics_summary,
       ics_data_t.col003 as ics_description,
       ics_data_t.col004 as ics_status,
                       'YYYY-MM-DD HH24:MI:SSTZH:TZM') as ics_dtstart,
                       'YYYY-MM-DD HH24:MI:SSTZH:TZM') as ics_dtend,
                       'YYYY-MM-DD HH24:MI:SSTZH:TZM') as ics_dtstamp,
       ics_data_t.col008 as ics_location,
       ics_data_t.col009 as ics_class,
       ics_data_t.col010 as ics_url,
       ics_data_t.col011 as ics_organizer,
       ics_data_t.col012 as ics_geo,
       ics_data_t.col013 as ics_created,
       ics_data_t.col014 as ics_last_modified
  from table(apex_data_parser.parse(p_content   => apex_web_service.make_rest_request_b('https://calendar.google.com/calendar/ical/#PUBLIC_CALENDAR_ID#/public/basic.ics',
                                    p_file_name => 'basic.ics')) ics_data_t;


Such a query can then be provided as the region source of a Calendar Region.

Besides the removed features, advanced custom JavaScript code or provided JavaScript Initialization code must also be reviewed and adjusted. FullCalendar version 5 changed the API, objects and methods as well as the naming of a lot of commonly used options - and as already said - moment.js objects became native date objects.

For further information about all options and possibilities, have a look at the official FullCalendar documentation. If someone is interested in what exactly has changed between version 3 and the current version 5, there are upgrade guides available as well:

JavaScript Initialization Code

These are 2 examples to compare the same functionality between the old version 3 and version 5:

function ( pOptions ) {
   pOptions.titleFormat            = "[Conference Schedule]";
   pOptions.minTime                = "07:00:00";
   pOptions.maxTime                = "21:00:00";
   pOptions.columnFormat           = { month: '', week: 'dddd', day: 'dddd' };
   pOptions.slotDuration           = "00:15:00";
   pOptions.weekNumbers            = true;
   pOptions.weekNumberTitle        = "CW";
   pOptions.weekNumberCalculation  = "ISO";
   pOptions.displayEventTime       = true;
   pOptions.displayEventEnd        = false;
   pOptions.disableKeyboardSupport = true;
   pOptions.windowResize           = null;
   return pOptions;


function ( pOptions ) {
   pOptions.titleFormat            = function( pDate ) { return "Conference Schedule" };
   pOptions.slotMinTime            = "07:00:00";
   pOptions.slotMaxTime            = "21:00:00";
   pOptions.dayHeaderFormat        = { weekday: 'short', month: 'numeric', day: 'numeric' };
   pOptions.slotDuration           = "00:15:00";
   pOptions.weekNumbers            = true;
   pOptions.weekText               = "CW";
   pOptions.weekNumberCalculation  = "ISO";
   pOptions.displayEventTime       = true;
   pOptions.displayEventEnd        = false;
   pOptions.disableKeyboardSupport = true;
   pOptions.windowResize           = null;
   return pOptions;


Even though both code snippets would result in the same output, there are quite some differences between the versions:

  • titleFormat is now expecting a function returning the title
  • minTime / maxTime was renamed to slotMinTime / slotMaxTime
  • columnFormat was renamed to dayHeaderFormat and also the expected object has changed
  • weekNumberTitle was renamed to weekText

Custom JavaScript code utilizing FullCalendar's API

If developers did even more customization of their Calendar Regions by using FullCalendar's JavaScript API - e.g. providing custom navigation or adding events to the calendar programmatically - there are also some notable changes here.

Let's compare some commonly used API calls between the 2 versions:

  • Get a handle on the calendar object
// old version 3
var calendar = apex.region("#REGION_STATIC_ID#").widget().fullCalendar("getCalendar");

// new version 5
var calendar = apex.region("#REGION_STATIC_ID#").widget().data("fullCalendar");


  • Get calendar's view object
// old version 3
var view = apex.region("#REGION_STATIC_ID#").widget().fullCalendar("getView");

// new version 5
var view = apex.region("#REGION_STATIC_ID#").widget().data("fullCalendar").view;


  • Custom navigation within the calendar
// old version 3
apex.region("#REGION_STATIC_ID#").widget().fullCalendar("gotoDate", "YYYY-MM-DD");

// new version 5


More examples of both, JavaScript Initialization Code or advanced JavaScript API usage, can be found in the Sample Calendar app which already is adjusted to support the updated Calendar Region & FullCalendar version 5. Since this release it can be found in the APEX Sample Code repository on GitHub.

For those of you, which heavily used moment.js for date manipulation: We're planning to create our own date utility API in a future APEX release, which when ready, will support most of moment.js functionality, to make date operations & manipulations much easier to use.

We hope this post helps you to get your hands on the updated calendar component and make the upgrade experience much more straight forward, even when you used advanced features & customizations.

As a side note: We are also planning to remove the FullCalendar version 3 implementation completely in a future APEX release, so now would be the perfect time to upgrade your existing calendars! :)

Join the discussion

Comments ( 1 )
  • Hamid Saturday, May 15, 2021
    I think it will be very helpful for us
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.