Installation
composer require theabhishekin/filament-calendar
Publish the config (if needed):
php artisan vendor:publish --tag=filament-calendar-config
Basic Usage Register the widget in a Filament page/resource:
use TheAbhishekIN\FilamentCalendar\Widgets\Calendar;
public static function getWidgets(): array
{
return [
Calendar::make()
->query(fn () => YourEventModel::query())
->eventUrl(fn ($record) => route('events.show', $record))
->dateClick(fn ($date) => YourEventModal::make($date)),
];
}
First Use Case Display a month-view calendar for appointments with a "Create Appointment" modal:
Calendar::make()
->query(Appointment::query())
->eventUrl(fn ($record) => route('appointments.show', $record))
->dateClick(fn ($date) => AppointmentModal::make($date))
->views(['dayGridMonth', 'timeGridWeek'])
Data Integration
query() to bind an Eloquent query builder. Example:
->query(fn () => Event::where('is_published', true)->orderBy('starts_at'))
eventFormatter():
->eventFormatter(fn ($event) => [
'title' => $event->title,
'start' => $event->starts_at->format('Y-m-d\TH:i:s'),
'end' => $event->ends_at->format('Y-m-d\TH:i:s'),
'color' => $event->color_hex,
'url' => route('events.show', $event),
])
Modal Integration
->dateClick(fn ($date) => EventModal::make($date))
->eventClick(fn ($event) => redirect($event->url))
Filtering
staff, status):
->filters(['staff', 'status'])
filtersForm() in a custom widget class:
public function filtersForm(): array
{
return [
Select::make('event_type')
->options(EventType::all()->pluck('name', 'id')),
];
}
View Customization
dayGridMonth, timeGridWeek, timeGridDay, listWeek.defaultView():
->defaultView('timeGridWeek')
->views(['dayGridMonth', 'timeGridWeek'])
Styling
color() to set default event colors:
->color('#3b82f6') // Default blue
Dynamic Data Loading
livewire:model to update events in real-time:
public function updatedSearch($search)
{
$this->query()->where('title', 'like', "%{$search}%");
}
Event Actions
->eventActions([
Action::make('edit')
->url(fn ($record) => route('events.edit', $record)),
Action::make('delete')
->requiresConfirmation()
->action(fn ($record) => $record->delete()),
])
External Integration
eventFormatter:
->eventFormatter(fn ($event) => [
'start' => $event->google_event->start->format('Y-m-d\TH:i:s'),
// ...
])
Date Formatting
starts_at/ends_at are Carbon instances or ISO strings (Y-m-d\TH:i:s). Non-compliant formats may break event rendering.->format('Y-m-d\TH:i:s') in eventFormatter.Modal Persistence
dateClick or eventClick with modals, ensure the modal’s Livewire component is properly scoped to avoid duplicate instances.->mountUsing(fn () => new YourModal()) in the modal class.Filter Query Binding
updatedFilters() in your Livewire component:
public function updatedFilters(array $filters)
{
$query = Event::query();
if (isset($filters['staff'])) {
$query->where('staff_id', $filters['staff']);
}
$this->query = $query;
}
Event Overlap Handling
eventFormatter may break this. Ensure start/end are properly formatted.Dark Mode Conflicts
->extraAttributes(['class' => 'dark:bg-gray-800'])
Console Logs
'calendar' => [
'debug' => env('FILAMENT_CALENDAR_DEBUG', false),
],
Query Logging
->toSql() to your query in eventFormatter to verify SQL:
dd($this->query()->toSql());
Event Data Validation
eventFormatter output matches FullCalendar’s expected structure:
[
'title' => string,
'start' => string (ISO 8601),
'end' => string (ISO 8601),
'allDay' => bool (optional),
'color' => string (hex, e.g., '#3b82f6'),
]
Custom Views
class CustomCalendar extends Calendar
{
public function customizeView(): void
{
$this->extraAttributes(['data-custom' => 'true']);
}
}
Alpine.js Extensions
php artisan vendor:publish --tag=filament-calendar-assets
document.addEventListener('alpine:init', () => {
Alpine.directive('custom-directive', (el, { expression }) => {
// Logic here
});
});
Event Drop/Resize
eventDrop and eventResize:
->eventDrop(fn ($event) => $event->update(['ends_at' => $event->end]))
->eventResize(fn ($event) => $event->update(['ends_at' => $event->end]))
Localization
'calendar' => [
'locale' => 'es',
],
fullcalendar-locale-es).How can I help you explore Laravel packages today?