DEV Community

Ayako yk
Ayako yk

Posted on

Learning FullCalendar Part 2: Building Your First Calendar App

This is Part 2 of the FullCalendar blog articles. The previous one covered the very basics to get you started. In this blog post, I'll focus on practical aspects and share some of the code I applied in my project.

My task was to concentrate solely on rendering dates with events, without incorporating features such as creating, editing, dragging, or deleting. To keep it simple, I opted for hard-coded data for events instead of setting up a database.

Additionally, the task required the calendar to be displayed in Japanese, and I'll share the relevant code for achieving this. Notably, I won't be using jQuery.

Let's get started.
(The final demo is available at the bottom.)

Laravel 10
Livewire v.3
FullCalendar v.6

Initialization

calendar.blade.php

Image description

I used the following code for validRange:

  validRange: function(nowDate) {
    return {
      start: nowDate,
      end: nowDate.clone().add(1, 'months')
    };
  }
Enter fullscreen mode Exit fullscreen mode

Unfortunately, this code resulted in an error, specifically, "nowDate.clone is not a function." To work around this issue and achieve my intended functionality of keeping the end date open, I modified the code to include only the start date:

validRange: function(nowDate) {
    return {
        start: nowDate,
    };
}
Enter fullscreen mode Exit fullscreen mode

With this adjustment, I can select dates starting from nowDate while leaving the end date open.

Image description

events

public $events = [
    [
        'id' => 101,
        'start' => '2023-09-20',
        'display' => 'background'
    ],
...
];
Enter fullscreen mode Exit fullscreen mode

In my case:
title is not needed because event names should not be displayed.
display => background is necessary to highlight the dates with events.
allDay might not be necessarily defined because a date will be highlighted with the setup of display => background even though the event is shown in the all-day section of relevant views.

Image description

The @json directive is used to convert the PHP array into its JSON representation.
The events configuration option specifies the source of events to be displayed on the calendar.
In this example, a hardcoded dataset is used, but it is common practice to store and retrieve data from a database or any other desired structure.
Since the $events variable is set to public, the events are rendered when the DOM is loaded.

public function mount()
{
    $this->getEvent();
}

public function getEvent()
{
    // Query data from the database
}
Enter fullscreen mode Exit fullscreen mode

Calendar.php

Image description

Image description

Here are some functions for controlling the calendar.

dateClick

Image description

dateClick triggers when the user clicks on a date or a time.
function( dateClickInfo ) { }
dateClickInfo has properties such as date and a useful one dateStr (e.g., '2023-10-01') that can be sent to the backend.

I wanted to add a red border around the clicked date, and we can achieve this by applying a classname defined separately in the style tag. Additionally, I wanted to display only the events that occur on or after the selected day, which is handled by a function defined in the backend using the selectedDay.

Let's take a look at what info has:

dateClick: function (info) {
       console.log('info', info);
Enter fullscreen mode Exit fullscreen mode

Image description

datesSet

Image description

datesSet is "[c]alled after the calendar’s date range has been initially set or changed in some way and the DOM has been updated."
function( dateInfo )
dateInfo has properties such as start, end, startStr, and view. The View Object contains information about the calendar view, including title that I can use to retrieve the current month.

When clicking a day or the next button to navigate to a different month, the calendar disappears briefly after the view changes. I attempted to use refetchEvents and added a new function to retrieve updated data, but these solutions didn't work. The new version of FullCalendar will handle data fetching automatically. The issue was that I had forgotten to use wire:ignore.

Image description

The wire:ignore directive in Livewire is used to instruct Livewire to ignore a specific portion of the DOM during Livewire component updates. This is necessary because FullCalendar is a JavaScript library that manages its own rendering and event handling. When you integrate FullCalendar into a Livewire component, not using wire:ignore can lead to Livewire attempting to re-render the FullCalendar component when the Livewire component state changes, causing issues with FullCalendar's functionality.

This is the final version of the app. I believe it's simplified enough to demonstrate the basic usage. Please pardon the design:)

Image description

Top comments (0)