diff --git a/README.md b/README.md index 6959137..83dab11 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,9 @@ use Saade\FilamentFullCalendar\Widgets\FullCalendarWidget; class CalendarWidget extends FullCalendarWidget { - + /** + * Return events that should be rendered statically on calendar first render. + */ public function getViewData(): array { return [ @@ -84,10 +86,22 @@ class CalendarWidget extends FullCalendarWidget ] ]; } + + /** + * 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. + */ + public function fetchEvents(array $fetchInfo, array $ignorableIds): array + { + // You can use $fetchInfo to filter events by date, and $ignorableIds to ignore already displayed events. + return []; + } } ``` -> You should return an array of FullCalendar [EventObject](https://fullcalendar.io/docs/event-object). +You can use one or both methods to fetch events. + +> Both methods should retun an array of [EventObject](https://fullcalendar.io/docs/event-object).
@@ -132,7 +146,7 @@ return [ # Listening for events -The only events supported right now are: [EventClick](https://fullcalendar.io/docs/eventClick) and [EventDrop](https://fullcalendar.io/docs/eventDrop) +The only event-related events supported right now are: [EventClick](https://fullcalendar.io/docs/eventClick) and [EventDrop](https://fullcalendar.io/docs/eventDrop) They're commented out by default so livewire does not spam requests without they being used. You are free to paste them in your `CalendarWidget` class. See: [FiresEvents](https://github.com/saade/filament-fullcalendar/blob/main/src/Widgets/Concerns/FiresEvents.php) @@ -171,7 +185,14 @@ The process of saving and editing the event is up to you, since this plugin does ## Creating Events: -Override the `createEvent` function in your widget class, and you are ready to go! +Events can be created in two ways. + +- Clicking on a day (default) +- Selecting a date range (click and drag across calendar days) (you need to opt-in for this, set `selectable => true` in the config file.) + +This will open the Create Event modal. + +When the create form gets submitted, it will call the `createEvent` function on your widget. Be sure to add the snippet below to your calendar class. ```php public function createEvent(array $data): void @@ -200,7 +221,11 @@ protected static function getCreateEventFormSchema(): array ## Editing Events: -Override the `editEvent` function in your widget class, and you are ready to go! +Events can be edited by clicking on an event on the calendar. + +This will open the Edit Event modal. + +When the edit form gets submitted, it will call the `editEvent` function on your widget. Be sure to add the snippet below to your calendar class. ```php public function editEvent(array $data): void @@ -271,6 +296,50 @@ public function yourMethod(): void
+# Filtering events based on the calendar view + +If you want to filter your events based on the days that are currently shown in the calendar, you can implement the `fetchInfo()` method from the [CanFetchEvents](https://github.com/saade/filament-fullcalendar/blob/main/src/Widgets/Concerns/CanFetchEvents.php) trait. Add the following code to your calendar widget: + +```php +/** + * FullCalendar will call this function whenever it needs new event data. + * This is triggered when the user clicks prev/next or switches views. + * + * @see https://fullcalendar.io/docs/events-function + * @param array $fetchInfo start and end date of the current view + * @param array $ignorableIds ids of the events that are already loaded and should be ignored + */ +public function fetchEvents(array $fetchInfo, array $ignorableIds): array +{ + return []; +} +``` + +you can filter events based on the timespan `$fetchInfo['start']` and `$fetchInfo['end']`. +> **Warning** +> +> Keep in mind that returning events that are already in the calendar, can cause duplicates. You should filter them out using the `$ignorableIds` ids. + +example: +```php +public function fetchEvents(array $fetchInfo, array $ignorableIds): array +{ + $schedules = Appointment::query() + ->where([ + ['start_at', '>=', $fetchInfo['start']], + ['end_at', '<', $fetchInfo['end']], + ]) + ->whereNotIn('id', $ignorableIds) + ->get(); + + $data = $schedules->map( ... ); + + return $data; +} +``` + +
+ ## Testing ```bash diff --git a/resources/views/fullcalendar.blade.php b/resources/views/fullcalendar.blade.php index 7103ce9..032f68e 100644 --- a/resources/views/fullcalendar.blade.php +++ b/resources/views/fullcalendar.blade.php @@ -1,4 +1,4 @@ -@php($locale = strtolower(str_replace('_', '-', $this->getConfig()['locale']))) +@php($locale = strtolower(str_replace('_', '-', $this->config('locale', config('app.locale'))))) @@ -8,8 +8,11 @@ x-init=' document.addEventListener("DOMContentLoaded", function() { const config = @json($this->getConfig()); - const events = @json($events); const locale = "{{ $locale }}"; + const events = @json($events); + const cachedEventIds = [ + ...events.map(event => event.id), + ]; const eventClick = function ({ event, jsEvent }) { if( event.url ) { @@ -41,21 +44,40 @@ @endif } + const fetchEvents = function ({ start, end }, successCallback, failureCallback) { + @if( $this::canFetchEvents() ) + return $wire.fetchEvents({ start, end }, cachedEventIds) + .then(events => { + // Cache fetched events + cachedEventIds.push(...events.map(event => event.id)); + + return successCallback(events); + }) + .catch( failureCallback ); + @else + return successCallback([]); + @endif + } + const calendar = new FullCalendar.Calendar($el, { ...config, locale, - events, eventClick, eventDrop, dateClick, select, + eventSources:[ + { events }, + fetchEvents + ] }); calendar.render(); - window.addEventListener("filament-fullcalendar:refresh", (event) => { + window.addEventListener("filament-fullcalendar:refresh", () => { calendar.removeAllEvents(); - event.detail.data.map(event => calendar.addEvent(event)); + cachedEventIds.length = 0; + calendar.refetchEvents(); }); }) '> diff --git a/src/Widgets/Concerns/CanFetchEvents.php b/src/Widgets/Concerns/CanFetchEvents.php new file mode 100644 index 0000000..9a6b724 --- /dev/null +++ b/src/Widgets/Concerns/CanFetchEvents.php @@ -0,0 +1,25 @@ +dispatchBrowserEvent('filament-fullcalendar:refresh', ['data' => $this->getViewData()]); + $this->dispatchBrowserEvent('filament-fullcalendar:refresh'); } } diff --git a/src/Widgets/Contracts/LazyLoading.php b/src/Widgets/Contracts/LazyLoading.php new file mode 100644 index 0000000..c81994b --- /dev/null +++ b/src/Widgets/Contracts/LazyLoading.php @@ -0,0 +1,8 @@ +