Upgrading a customized Full Calendar component

Anna Lysek | proudly auDHD
Noesis Low-Code Solutions
7 min readJul 9, 2020

How to drag and drop multiple external events simultaneously with the Full Calendar

On one very normal workday, I was proposed a challenge: upgrading an already customized Full Calendar component that was being used in one of the factory’s applications to a newer version of the same component.

It made sense: the version that was being used was almost 4 years old, and there were deprecation warnings in the console whenever the calendar widget was rendered. New developments were going to be implemented anyway so the upgrade would mean killing two birds with one stone.

Deprecation warning as seen in the console

Rolling up my sleeves I got to work, and the first step was analyzing the code in the current customized component. For context, the Full Calendar component imports a series of libraries and uses JavaScript code in an unescaped expression to render the calendar on the screen it is being used on. This is true both for the older and the newer versions.

Full Calendar version 3.0.0 web block

The most important existing customizations were in the unescaped expression, so I focused my attention on that code. The previous version in use was customized to allow a Drag and Drop functionality in conjunction with a separate component.

Customized JavaScript as I’ve found it

An external event (event from outside the calendar) would be dropped onto the calendar from a list on the screen and since the ‘droppable’ property is set to True, the function in the ‘drop’ property would run and a corresponding event would be rendered on the calendar.

The code above made it happen. The communication with the parent screen was done through a hidden input, which received the information of the rendered event, and a click on a hidden link that propagated that information to the parent screen to be treated adequately.

After analyzing the code in the old version, the next step was to get the existing customizations to work in the new version of the component.

The new version is based on the most recent version of the JavaScript calendar so there were differences in code syntax and also functionalities between the older version and the newer one. Therefore, the first challenge here was adapting existing code to the new syntax. The source component’s documentation (https://fullcalendar.io/) was very helpful here.

The original component’s documentation at https://fullcalendar.io/

The real challenge turned out to be that the new version of the calendar didn’t want to play nice with the particular Drag and Drop component that the older version was using. Nothing happened when a drop occurred. No screen event was triggered, nothing came up in debug. Off to a great start!

A bit of digging in the source component’s documentation (https://fullcalendar.io/) gave me some ideas. An external drag and drop functionality for this new version was already contemplated, as can be seen in the demo:

External drag and drop demo from the original Full Calendar documentation

It requires a set of containers with specific style classes to be used as selectors. That’s the bones of the new draggable, but an “OnDomContentLoaded” event listener is what makes the magic happen.

The listener selects elements that have the selector class ‘DraggedItem’ and are inside a container with the class ‘external-events’. Important to note that this listener needs to be instantiated when screen elements are already loaded in the DOM to be able to select the calendar.

With that figured out, this was the first victory! But dragging and dropping one event at a time just wouldn’t cut it anymore. The idea was to be able to drag and drop multiple elements at the same time. That meant that it was necessary for the events to be selectable and have a list of the selected items stored as a serialized JSON list, that could be updated whenever one of the elements was selected/unselected. A hidden input seemed like a logical solution since a serialized list could be stored in it and read from within the calendar. jQuery comes in handy in such cases, just add a unique CSS class to the input and it can be found from anywhere on the screen.

The new version of the customized code reads the serialized JSON list stored in the hidden input, parses it to form an object list, iterates that list, and renders all the selected events one after the other on the calendar, based on the information in each object (e.g: duration, color, etc).

Further customized script that can receive multiple events simultaneously

The last thing that was missing was the communication between the JavaScript code of the calendar and the parent screen. The component came with a set of default screen events triggered from inside the calendar’s code, and while they worked well for interactions with events already rendered on the calendar, they weren’t working well with external events.

That’s where a small but powerful widget came in very handy.

Notice the small web block in the lower left corner

The TriggerEvent widget that was already being used in the new Full Calendar component.

It can be called from within the code. “You may (…) trigger the event by calling the TriggerEvents JavaScript function passing the block Id followed by the event parameters (e.g.: TriggerEvents(MyBlockCopy.Id, “My Name”);).” as is stated in the block’s description.

With this last step added to the end of the ‘drop’ function in the code, we now had the list of rendered events sent back to the parent screen.

The action that handled screen events triggered inside the calendar gained 3 custom branches, one that informed the parent screen of the rendered events, one that reacted to a validation that avoids events being dropped in the past, and a last one that reacted to an event being dropped on the calendar a second time. The latter 2 are just validations that show warnings on the screen.

The last requirement was to add another type of event to show holidays on the calendar. Holidays are best shown as background events, but by default, those don’t show a label. That required some trial and error since I couldn’t find anything about it in the component’s documentation. The only thing I could use as inspiration was the eventRender property in the calendar’s script:

A little adaptation and some trial and error attempts later, this is what I came up with:

This creates a div with a specific class (‘fc-bg-ev-desc’) inside the already existing div of the Background Event. Inside this div, we specify which elements of the event object are to be shown, in this case, the title and description. The class can be altered as needed to make sure the content is presented as we wish.

With that figured out, the only thing left to do was to merge it all together and look at the result. All together it works quite nicely if I say so myself. ;)

Demo of the new features

In conclusion, the upgrade had its ups and downs, but it was ultimately a very gratifying challenge, which helped me grow immensely as a programmer, both in my use of JavaScript, and OutSystems.

--

--