ancarebeca/full-calendar-bundle
Install the Bundle
composer require ancarebeca/full-calendar-bundle
Enable the Bundle
Add to config/bundles.php:
return [
// ...
AncaRebeca\FullCalendarBundle\FullCalendarBundle::class => ['all' => true],
];
Create a Custom Event Class
Extend FullCalendarEvent in your entity:
// src/Entity/CalendarEvent.php
namespace App\Entity;
use AncaRebeca\FullCalendarBundle\Model\FullCalendarEvent;
class CalendarEvent extends FullCalendarEvent
{
// Add custom fields (e.g., title, description, etc.)
}
Create a Data Loader Listener Implement a service to fetch events:
// src/EventListener/CalendarDataListener.php
namespace App\EventListener;
use AncaRebeca\FullCalendarBundle\Model\FullCalendarEvent;
use App\Entity\CalendarEvent;
class CalendarDataListener
{
public function loadData(FullCalendarEvent $event)
{
$events = $this->fetchEventsFromDatabase(); // Your logic
foreach ($events as $dbEvent) {
$event->addEvent(new CalendarEvent(
$dbEvent->getTitle(),
$dbEvent->getStartDate(),
$dbEvent->getEndDate()
));
}
}
}
Register the listener in config/services.yaml:
services:
App\EventListener\CalendarDataListener:
tags:
- { name: 'kernel.event_listener', event: 'fullcalendar.set_data', method: 'loadData' }
Add Assets to Twig
Include in your template (templates/base.html.twig):
{% block stylesheets %}
<link rel="stylesheet" href="{{ asset('bundles/fullcalendar/css/fullcalendar.min.css') }}">
{% endblock %}
{% block javascripts %}
<script src="{{ asset('bundles/fullcalendar/js/fullcalendar/lib/jquery.min.js') }}"></script>
<script src="{{ asset('bundles/fullcalendar/js/fullcalendar/lib/moment.min.js') }}"></script>
<script src="{{ asset('bundles/fullcalendar/js/fullcalendar/fullcalendar.min.js') }}"></script>
<script src="{{ asset('bundles/fullcalendar/js/fullcalendar/fullcalendar.default-settings.js') }}"></script>
{% endblock %}
Render the Calendar Add to your template:
{% include '@FullCalendar/Calendar/calendar.html.twig' %}
Install Assets
php bin/console assets:install public
Dynamic Event Loading
Use the fullcalendar.set_data event to fetch events dynamically (e.g., via AJAX):
// In your listener
public function loadData(FullCalendarEvent $event)
{
$start = $event->getStart()->format('Y-m-d');
$end = $event->getEnd()->format('Y-m-d');
$events = $entityManager->getRepository(CalendarEvent::class)
->findByDateRange($start, $end);
foreach ($events as $eventEntity) {
$fcEvent = new CalendarEvent(
$eventEntity->getTitle(),
$eventEntity->getStart(),
$eventEntity->getEnd()
);
$fcEvent->setAllDay($eventEntity->isAllDay());
$fcEvent->setBackgroundColor('#3788d8');
$event->addEvent($fcEvent);
}
}
Customizing Calendar Views
Override the default JavaScript settings by copying fullcalendar.default-settings.js to your bundle’s Resources/public/js/ and extend it:
// YourBundle/Resources/public/js/fullcalendar.custom.js
$(document).ready(function() {
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: true,
eventClick: function(event) {
// Custom logic (e.g., open a modal)
alert('Event clicked: ' + event.title);
}
});
});
Integration with Forms Use Symfony Forms to create/edit events:
{{ form_start(form) }}
{{ form_row(form.title) }}
{{ form_row(form.start) }}
{{ form_row(form.end) }}
<button type="submit">Save Event</button>
{{ form_end(form) }}
Handle form submission in your controller to persist the event.
Timezone Handling
Ensure timezone consistency by setting the timezone option in JavaScript:
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
Or force a specific timezone in your PHP logic:
$event->setStart(new \DateTime($startDate, new \DateTimeZone('Europe/London')));
Lazy Loading
Enable lazyFetching: true in JavaScript to load events on-demand:
eventSources: [
{
url: '/full-calendar/load',
type: 'POST',
data: {
start: function() { return $('#calendar').fullCalendar('getView').start.getTime(); },
end: function() { return $('#calendar').fullCalendar('getView').end.getTime(); }
}
}
]
Outdated Dependencies
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/main.min.js"></script>).Resources/public/ directory.Asset Paths
web/bundles/fullcalendar/. If using Symfony Flex or custom paths:
<link rel="stylesheet" href="{{ asset('build/css/fullcalendar.min.css') }}">
config/packages/asset.yaml.Event Data Serialization
CalendarEvent implements __toString() or provides a getTitle() method for display in the calendar.public function getTitle(): string
{
return $this->title;
}
Listener Timing
fullcalendar.set_data event fires before rendering the calendar. If events don’t appear:
services.yaml.DateTime Formatting
\DateTime objects:
$event->setStart($dateTime->getTimestamp() * 1000); // Milliseconds
Or use ISO format:
$event->setStart($dateTime->format('Y-m-d\TH:i:s'));
Routing Conflicts
/full-calendar/. If you customize the route:
eventSources.url in JavaScript to match your route (e.g., /api/events).CORS Issues (AJAX)
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
$response = new Response(json_encode($events));
$response->headers->set('Access-Control-Allow-Origin', '*');
return $response;
Debugging Event Data
public function loadData(FullCalendarEvent $event)
{
dump($event->getStart(), $event->getEnd(), $event->getFilters());
}
/full-calendar/load.Custom Event Colors
$event->setBackgroundColor($this->getColorByType($eventEntity->getType()));
Define a helper method:
private function getColorByType(string $type): string
{
return match ($type) {
'meeting' => '#3788d8',
'holiday' => '#f7b733',
default => '#4CAF50',
};
}
3
How can I help you explore Laravel packages today?