Laravel Filament provides a fantastic administrative panel builder for Laravel applications. When it comes to displaying dynamic events, tasks, or schedules, integrating a robust calendar solution like FullCalendar is a common requirement. This post will guide you through adding FullCalendar to your Laravel Filament widgets, highlighting key configurations and, crucially, providing solutions to common errors you might encounter.
Why FullCalendar in Laravel Filament?
FullCalendar is a versatile JavaScript calendar library that allows you to create interactive and customizable calendars. Integrating it into Filament widgets empowers you to build powerful dashboards for:
- Event Management: Displaying conferences, webinars, or social events.
- Task Scheduling: Visualizing project timelines and deadlines.
- Resource Booking: Showing availability of rooms, equipment, or staff.
- Appointment Management: For clinics, salons, or service-based businesses.
The easiest way to achieve this integration is by using the excellent saade/filament-fullcalendar
plugin.
Prerequisites
- Laravel v10+ Installed
- Filament v3+ Installed with Panel builder
Step 1: Installation and Basic Setup
First, ensure you have a Laravel Filament project set up. Then, install the fullcalendar plugin via Composer:
composer require saade/filament-fullcalendar:^3.0
After installation, this plugin needs to be registered in your Filament panel provider, typically app/Providers/Filament/AdminPanelProvider.php
:
use Saade\FilamentFullCalendar\FilamentFullCalendarPlugin;
use Filament\Panel;
use Filament\PanelProvider;
class AdminPanelProvider extends PanelProvider
{
public function panel(Panel $panel): Panel
{
return $panel
// ... other panel configurations
->plugins([
FilamentFullCalendarPlugin::make()
// You can add global configurations here, e.g., ->selectable(true)
]);
}
}
Step 2: Implementing the Calendar Widget
Now, generate a new Filament widget for your calendar:
php artisan make:filament-widget CalendarWidget
It will create a file app/Filament/Widgets/CalendarWidget.php
. Update this file to extend Saade\FilamentFullCalendar\Widgets\FullCalendarWidget
.
namespace App\Filament\Widgets;
use Saade\FilamentFullCalendar\Widgets\FullCalendarWidget;
use Illuminate\Database\Eloquent\Model; // If you're fetching from a model
use App\Models\Event; // Example: Replace with your event model
class CalendarWidget extends FullCalendarWidget
{
// If you have a dedicated model for events, you can specify it here.
// This allows for default create/edit/delete actions.
public Model | string | null $model = Event::class; // Replace 'Event::class' with your actual model
/**
* FullCalendar will call this function whenever it needs new event data.
* This is triggered when the user clicks prev/next or switches views on the calendar.
*
* @param array $fetchInfo An array containing 'start', 'end', and 'timezone' for the current view.
* @return array
*/
public function fetchEvents(array $fetchInfo): array
{
// Example: Fetch events from your 'Event' model within the visible date range
return Event::query()
->where('start_date', '>=', $fetchInfo['start']) // Assuming 'start_date' and 'end_date' columns
->where('end_date', '<=', $fetchInfo['end'])
->get()
->map(fn (Event $event) => [
'id' => $event->id,
'title' => $event->name, // Replace with your event title column
'start' => $event->start_date, // Replace with your event start date column
'end' => $event->end_date, // Replace with your event end date column
// You can add more FullCalendar event properties here
// 'url' => EventResource::getUrl(name: 'view', parameters: ['record' => $event]),
// 'shouldOpenUrlInNewTab' => true,
// 'color' => '#f00',
])
->toArray();
}
/**
* You can customize FullCalendar options by overriding the config method.
*/
public function config(): array
{
return [
'initialView' => 'dayGridMonth',
'headerToolbar' => [
'left' => 'prev,next today',
'center' => 'title',
'right' => 'dayGridMonth,timeGridWeek,timeGridDay',
],
// ... more FullCalendar options
// 'editable' => true, // Enable dragging and resizing if your model allows
// 'selectable' => true, // Enable date selection to create new events
];
}
}
Key Components:
$model
Property: Crucial for the plugin’s built-in actions (create, edit, view, delete) to understand which database model your events belong to.
use App\Models\Event; // Make sure your Event model exists
class CalendarWidget extends FullCalendarWidget
{
public Model | string | null $model = Event::class;
// ...
}
fetchEvents(array $fetchInfo)
: This method is called by FullCalendar to retrieve event data for the currently displayed date range. You should query your database and return an array of event objects, each with at leastid
,title
,start
, andend
properties.
public function fetchEvents(array $fetchInfo): array
{
return Event::query()
->where('start_date', '>=', $fetchInfo['start'])
->where('end_date', '<=', $fetchInfo['end'])
->get()
->map(fn (Event $event) => [
'id' => $event->id,
'title' => $event->name,
'start' => $event->start_date,
'end' => $event->end_date,
// Add more properties like 'color', 'classNames', 'url' etc.
])
->toArray();
}
config(): array
: This method is where you configure all of FullCalendar’s JavaScript options for your specific widget instance (e.g., initial view, toolbar buttons, event display format, etc.).
public function config(): array
{
return [
'initialView' => 'dayGridMonth',
'headerToolbar' => [
'left' => 'prev,next today',
'center' => 'title',
'right' => 'dayGridMonth,timeGridWeek,timeGridDay',
],
// 'selectable' => true, // Allows clicking/dragging to select dates
// 'editable' => true, // Allows dragging/resizing events
// ... many more FullCalendar options
];
}
Step 3: Final Touches
Add the Widget: Ensure your CalendarWidget::class
is listed in the widgets
options of your app/Providers/Filament/AdminPanelProvider.php
to display it on the dashboard.
use App\Filament\Widgets\CalendarWidget;
use Saade\FilamentFullCalendar\FilamentFullCalendarPlugin;
use Filament\Panel;
use Filament\PanelProvider;
class AdminPanelProvider extends PanelProvider
{
public function panel(Panel $panel): Panel
{
return $panel
// ... other panel configurations
->widgets([
CalendarWidget::class, // add your calendar widget class here
])
->plugins([
FilamentFullCalendarPlugin::make()
// You can add global configurations here, e.g., ->selectable(true)
]);
}
}
Composer Autoload & Cache: After any class changes or file movements, always run the following commands:
composer dump-autoload
php artisan optimize:clear
php artisan filament:clear-cached-components # Useful for Filament-specific cache
Verify Data: Use dd()
liberally in your fetchEvents()
and mountUsing()
methods to inspect the data being passed, especially id
values, to ensure they match your database primary keys. So, you can extend the development to open event view panel on any event click.
Conclusion
By following these steps, you can successfully integrate and customize FullCalendar within your FilamentPHP widgets, creating a powerful and interactive event management dashboard. For more advanced configurations, always refer to the official FullCalendar documentation
and the saade/filament-fullcalendar
plugin’s GitHub repository.