All You Need to Know about a FullCalendar View Module

Aug 27, 2021
By Ihor
Drupal

Working on one of the Five Jars projects, we bumped into the need to create an event calendar. We wanted it to be lightweight yet powerful enough to support all the required features. After research and consideration, we've finally chosen the FullCalendar View module. In this post, we will talk about this awesome library. Spoiler: here is what we’ve got:

Fullcalendar View module: final result

Now let's get down to the details.

 

What is Fullcalendar?

FullCalendar is a JavaScript library that seamlessly integrates with such popular JavaScript frameworks as Vue, React, Angular. Thanks to its excellent documentation, one won’t have trouble incorporating the library into projects. Besides, it’s easy to test different modes (day, week, month), themes, and features with the demo version provided.

Demos calendar Drupal

The library also has a paid version with additional features like Timeline View, Vertical Resource View, and Printer-friendly rendering. We were satisfied with the standard version, though.

 

Integration with Drupal

When it comes to Drupal, it’s a good idea to use the Fullcalendar View module. Some of the editorial features it provides:

  • creating a new event by double-clicking;
  • event drag and drop;
  • resize event.

The module works with the FullCalendar 4.4.2 version, but it might be updated to version 5 soon

How to Configure Content and Views for FullCalendar?

First, the module has to be installed, but the process is straightforward, so let’s skip the explanation.

Once done with the installation, you have to add a date field to your node type. This module supports such fields as:

  • timestamp;
  • datetime;
  • date range.

In this project, we used the date range field, so the configuration examples are based on this field.

The next step is to create views with the Full Calendar Display format:

Full calendar display

Add node title, description, and date fields to views. After this, configure Full Calendar Display in the format settings:

  1. Select the Default date source. Based on this value, the date of the calendar beginning will be selected.
  2. Select start and end date fields. For the date range, this will be the same field.
  3. Select the title field.
  4. Select a node type (Then, to create a new node in the calendar view, one will have to simply double-click on the time slot.)
Editor schedule in Drupal

The display section of format settings also contains several configurations:


Most of them are related to the FullCalendar JavaScript library settings and are described in the documentation

In this section, you can allow editing events, add confirmation popups, and set limits for one day.

There is also a Legend Colors section:

Legend colors

To use color taxonomy, create taxonomy vocabulary and add a field with reference to this taxonomy in your content type. If you display different content types in views, you can select a specific color for each bundle.

 

Customization

The module provides FullcalendarViewProcessor plugins that are essentially wrappers for template preprocess. You can create an instance of this plugin in the Plugin/FullcalendarViewProcessor directory and add your customizations. Alternatively, you can use template_preprocess_views_view_fullcalendar. In the calendar_options you can set backgroundColor, borderColor, classNames, etc for each calendar record. For instance, add different classes based on the moderation state and change opacity or item styles in the theme.

Customizations example:

/**

* Implements template_preprocess_views_view_fullcalendar().

*/

function test_preprocess_views_view_fullcalendar(array &$variables) {

 if (!isset($variables['#attached']['drupalSettings']['fullCalendarView'][0]['calendar_options'])) {

   return;

 }


 $calendar_options = &$variables['#attached']['drupalSettings']['fullCalendarView'][0]['calendar_options'];

 $options = json_decode($calendar_options, TRUE);

 // Display now indicator.

 $options['nowIndicator'] = TRUE;

 // Show calendar in user account's timezone.

 $options['timeZone'] = date_default_timezone_get();

 $options['plugins'][] = 'momentTimezone';

 
 if (!empty($options['events'])) {

   foreach ($options['events'] as &$event) {

     _test_fullcalendar_event_alter($event);

   }

 }

 $calendar_options = json_encode($options);

}

 
/**

* Updates the fullcalendar event item.

*

* Sets background color, additional CSS classes, changes URL, etc.

*

* @param array $event

*   The event array.

*/

function _test_fullcalendar_event_alter(array &$event) {

 $node = \Drupal::entityTypeManager()

   ->getStorage('node')

   ->load($event['eid']);

 
 if (!$node->isLatestRevision()) {

   $storage = \Drupal::entityTypeManager()->getStorage('node');

   $revision_ids = $storage->revisionIds($node);

   $latest_revision_id = end($revision_ids);

   $node = $storage->loadRevision($latest_revision_id);

 }

 
 $event['backgroundColor'] = _test_get_color($node);

 $event['borderColor'] = $event['backgroundColor'];

 $event['classNames'] = _test_get_classnames($node);

 
 if (!$node->access('view')) {

   $event['url'] = '';

 }

 
 if ($node->access('update')) {

   $state = $node->moderation_state->value;

   $event['editable'] = !in_array($state, ['declined', 'canceled']);

   $event['url'] = $node->toUrl('edit-form')->toString();

 }

}

Issues

You may face some issues when using the Fullcalendar View module. Let’s have a look at the most common ones.

 

Loading items as needed by AJAX

You can meet this issue if there are many events because of the limits the calendar has. 

We faced this problem, too. In the described case, the calendar has a filter by association, and if it displays all events, we're stuck with the limits. Fortunately for us, the Fullcalendar library already includes the option to load data - events (as a JSON feed). We need to simply add this feature to the Drupal module:

1. Small hack in fullcalendar_view.js in the buildCalendars method:

delete calendarOptions.events;

calendarOptions.eventSources = [

 {

   url: '/api/example-events',

   method: 'GET',

   extraParams: {

     ajax: true,

   },

   failure: function() {

     alert('There was an error while fetching events!');

   },

 }

];
  • Unset calendarOptions events (this is values from views).
  • Add eventSources with URL to your custom controller.

2. In the views, add two exposed filters for your date field: Event date min and Event date max

Drupal calendar
Drupal calendar 2
  • The main thing in these fields is to set the Filter identifier to start/end because the Fullcalendar library gets these values from query parameters out of the box.
  • Don't forget to turn on Use AJAX in the views settings.
  • Hide exposed forms with CSS. These fields are needed only for the controller.

3. Create a custom controller that returns JsonResponse with the data for the calendar.

A simple example of such a controller:

/**

* Schedules page params.

*/

public function build(Request $request) {

 $ajax = (bool) $request->query->get('ajax');

 if (!$ajax) {

   throw new AccessDeniedHttpException();

 }

 $view = Views::getView('schedule');

 $display = 'page_1';

 $view->setDisplay($display);

 $view->preExecute();

 $view->execute();

 $content = $view->render($display);

 // We need render to execute all template_preprocess functions for

 // calendar_options.

 $this->renderer->renderRoot($content);

 $calendar_options = json_decode($content['#attached']['drupalSettings']['fullCalendarView'][0]['calendar_options'], TRUE);

 return new JsonResponse($calendar_options['events']);

}
  • As for views creation, we already have arguments from the request as filters, and during navigation through Fullcalendar these filters update and load new data. Also, they support a date range for different modes out of the box (for example, depending on the selected mod, week or month can be set between the start and end date).

 

Timezone

It was actually not an issue but more of an improvement. To correct the logic of timezone handling, we used the TimeZone Plugin, which is recommended in the official documentation.

1. Add the moment-timezone library.

libraries.moment-timezone:

 version: '0.5.33'

 js:

   https://unpkg.com/moment-timezone@0.5.33/builds/moment-timezone-with-data.min.js:

     type: external

     minified: true

 

2. Attach this library

/**

* Implements hook_library_info_alter().

*/

function test_library_info_alter(array &$libraries, $module) {

 if ($module !== 'fullcalendar_view') {

   return;

 }


 $libraries['libraries.fullcalendar']['dependencies'][] = 'test/libraries.moment-timezone';

 $libraries['libraries.fullcalendar']['js']['https://unpkg.com/@fullcalendar/moment-timezone@4.4.2/main.min.js'] = [

   'external' => TRUE,

   'minified' => TRUE,

 ];

}

In the template_preprocess_views_view_fullcalendar we need to set the timezone and add the momentTimezone plugin.

/**

* Implements template_preprocess_views_view_fullcalendar().

*/

function test_preprocess_views_view_fullcalendar(array &$variables) {

 if (!isset($variables['#attached']['drupalSettings']['fullCalendarView'][0]['calendar_options'])) {

   return;

 }


 $calendar_options = &$variables['#attached']['drupalSettings']['fullCalendarView'][0]['calendar_options'];

 $options = json_decode($calendar_options, TRUE);

 // Show the calendar in the user account's timezone.

 $options['timeZone'] = date_default_timezone_get();

 $options['plugins'][] = 'momentTimezone';

 $calendar_options = json_encode($options);

}

Conclusion

Fullcalendar View Module is a flexible and lightweight JavaScript library. It’s easy to integrate into various projects and configure according to the project’s needs. The module’s features are very well-documented, which makes the work with it even more pleasant.

Ihor
Ihor
Developer with 8 years of experience in developing web applications. His extensive expertise in web application integration with third-party services allowed him to succeed working on e-commerce projects, sites for startups, sites for Medicine & Health companies.

LET'S CONNECT

Get a stunning website, integrate with your tools,
measure, optimize and focus on success!