Reputation: 3081
In my Laravel 8 / jQuery 3.5.1 / bootstrap 4.5.3 app with FullCalendar v4.3.1 I show events only for current month and user can select month by clicking on Next Prior month arrows of the calendar.
I need to retrieve data from db only for selected month. I need to run data retrieve method when user clicks on Next Prior month arrows. I make it with datesRender event, but I got problems that datesRender is triggered again when data retrieved and I got endless triggering of this method.
I do :
jQuery(document).ready(function ($) {
adExpireDateEvenstLoadWithFullCalendar() // get data from db for selected month
...
}) // jQuery(document).ready(function ($) {
function adExpireDateEvenstLoadWithFullCalendar () { // get data from db for selected month
var dataArray = {
'_token': '{{ $csrf_token }}',
'year': select_year,
'month': parseInt(select_month) + 1
}
var href = "/admin/get_ad_events"
$.ajax({
type: "POST",
dataType: "json",
url: href,
data: dataArray,
success: function (response) {
initFullCalendar(response.events, response.calendar_events_default_date);
},
error: function (error) {
popupErrorMessage(error.responseJSON.message)
}
});
} // function adExpireDateEvenstLoadWithFullCalendar () { // get data from db for selected month
function initFullCalendar(eventsList, calendar_events_default_date) { // init FullCalendar with given array of data and month
if (typeof window.calendarEventsObject != "undefined") { // clear existing instance
window.calendarEventsObject.destroy();
}
var calendarEl = document.getElementById('expire_date_events_calendar');
var current_date = moment(calendar_events_default_date).format('YYYY-MM-DD')
var today = moment();
window.calendarEventsObject = new FullCalendar.Calendar(calendarEl, { // FullCalendar Init
plugins: ['dayGrid', 'timeGrid'],
defaultView: 'dayGridMonth',
views: {
dayGridMonth: {
buttonText: 'Month'
},
timeGridWeek: {
buttonText: 'Week'
}
},
axisFormat: "H:mm A",
timeFormat: "H:mm A",
header: {
left: 'dayGridMonth,timeGridWeek',
center: 'title',
right: 'today prev,next '
},
eventRender: function (eventInfo) {
...
}, // eventRender: function (eventInfo) {
dayRender: function (date) {
...
},
datesRender: function (view) {
select_year= view.view.currentStart.getFullYear()
select_month= view.view.currentStart.getMonth()
if (calendarExpireDateEventsObject) {
calendarExpireDateEventsObject.datepicker('setDate', new Date(select_year, select_month, 1)).trigger('change');
adExpireDateEvenstLoadWithFullCalendar() // I need to read data for selected month and THIS RAISE endless triggering of this method
}
}, // datesRender
select: function (start, end, allDay) {
...
},
events: eventsList,
defaultDate: current_date,
showNonCurrentDates: false,
displayEventTime: true,
eventLimit: true, // allow "more" link when too many events
editable: true,
allDaySlot: true,
selectable: true,
selectHelper: true,
selectOverlap: false,
fixedWeekCount: false,
disableDragging: true,
aspectRatio: 0.4,
height: 900,
eventClick: function (clickObj) {
...
return false;
},
}); // window.calendarEventsObject = new FullCalendar.Calendar(calendarEl, { // FullCalendar Init
// 'calendar_events_default_date' => '2019-08-22',
window.calendarEventsObject.render(
{
backgroundColor: 'green',
textColor: 'yellow',
}
);
jQuery('.eo-fullcalendar').on('click', '.fc-event', function (e) {
e.preventDefault();
...
});
} // function initFullCalendar(eventsList, calendar_events_default_date) { // init FullCalendar with given array of data and month
Any hints how that can be fixed ?
MODIFIED BLOCK : I found this https://fullcalendar.io/docs/v4/events-function page and try to use it in my blade page :
@section('scripts')
<link rel="stylesheet" href="{{ asset('/css/fullcalendar/core/main.css') }}" type="text/css">
<link rel="stylesheet" href="{{ asset('/css/fullcalendar/daygrid/main.css') }}" type="text/css">
<link rel="stylesheet" href="{{ asset('/css/fullcalendar/timegrid/main.css') }}" type="text/css">
<link href="{{ asset('css/gijgo.min.css') }}" rel="stylesheet" type="text/css">
<link href="{{ asset('css/jquery-ui.css') }}" rel="stylesheet" type="text/css">
<script src="{{ asset('js/moment.min.js') }}"></script>
<script src="{{ asset('js/popper.min.js') }}"></script>
<script src="{{ asset('js/bootstrap.min.js') }}"></script>
<script src="{{ asset('js/fullcalendar/core/main.js') }}"></script>
<script src="{{ asset('js/fullcalendar/daygrid/main.js') }}"></script>
<script src="{{ asset('js/fullcalendar/timegrid/main.js') }}"></script>
<script src="{{ url('js/jquery-ui.min.js') }}"></script>
<script>
let select_year = '{{ $select_year }}'
let select_month = '{{ $select_month }}'
let calendarExpireDateEventsObject = null
jQuery(document).ready(function ($) {
backendInit('list', 'expire_date_events_calendar')
// fullCalendarInit()
console.log('BEFORE::')
// import { req } from 'superagent'; // ajax library
var calendar = new Calendar(calendarEl, {
events: function(info, successCallback, failureCallback) {
req.get('myxmlfeed.php')
.type('xml')
.query({
start: info.start.valueOf(),
end: info.end.valueOf()
})
.end(function(err, res) {
if (err) {
failureCallback(err);
} else {
successCallback(
Array.prototype.slice.call( // convert to array
res.getElementsByTagName('event')
).map(function(eventEl) {
return {
title: eventEl.getAttribute('title'),
start: eventEl.getAttribute('start')
}
})
)
}
})
}
});
and I got error in the console :
jquery.min.js:2 Uncaught ReferenceError: Calendar is not defined
at HTMLDocument.<anonymous>
Maybe I missed some .js files ? included list of files worked ok for my priorcode... All files v4.3.0.
Thanks!
Upvotes: 0
Views: 1148
Reputation: 61904
You said
I need to run data retrieve method when user clicks on Next Prior month arrows
...but actually no, you don't. You need to follow the proper system for doing this which fullCalendar has provided. See https://fullcalendar.io/docs/v4/events-function . If you give fullCalendar a callback function which runs your AJAX request, it will automatically call that function whenever it needs new events (i.e. whenever the date range being displayed changes). It passes the current start/end dates into the function so that you can use them in your AJAX to send to the server. No need to mess with datesRender etc.
You seem to be having some trouble relating the documentation to your own code, so here is an example of how you should do it. Obviously I haven't tested this, but this should give you the right idea.
Also, currently you are sending month and year to your server, but fullCalendar will pass you specific start and end dates. You should send these to your server. Then you should modify the server code so that it returns all events within these start and end dates, rather than for a specific months. This is because if, for example, you are using the "week" view instead of the "month" view, the dates that fullCalendar sends will cover 1 week instead of 1 month. So you need a bit more flexibility than just returning a whole month of events.
jQuery(document).ready(function ($) {
loadCalendar(); //initialise the calendar
})
function loadCalendar() {
var calendarEl = document.getElementById('expire_date_events_calendar');
window.calendarEventsObject = new FullCalendar.Calendar(calendarEl, { // FullCalendar Init
plugins: ['dayGrid', 'timeGrid'],
defaultView: 'dayGridMonth',
views: {
dayGridMonth: {
buttonText: 'Month'
},
timeGridWeek: {
buttonText: 'Week'
}
},
axisFormat: "H:mm A",
timeFormat: "H:mm A",
header: {
left: 'dayGridMonth,timeGridWeek',
center: 'title',
right: 'today prev,next '
},
eventRender: function (info) {
//...
},
dayRender: function (dayRenderInfo) {
//...
},
select: function (selectionInfo) {
//...
},
events: function(info, successCallback, failureCallback) { //get data from db for selected dates
var dataArray = {
'_token': '{{ $csrf_token }}',
'start': info.startStr,
'end': info.endStr
}
var href = "/admin/get_ad_events";
$.ajax({
type: "POST",
dataType: "json",
url: href,
data: dataArray,
success: function (response) {
successCallback(response.events);
},
error: function (error) {
failureCallback(error);
popupErrorMessage(error.responseJSON.message);
}
});
},
showNonCurrentDates: false,
displayEventTime: true,
eventLimit: true, // allow "more" link when too many events
editable: true,
allDaySlot: true,
selectable: true,
selectHelper: true,
selectOverlap: false,
fixedWeekCount: false,
disableDragging: true,
aspectRatio: 0.4,
height: 900,
eventClick: function (eventClickInfo) {
//...
return false;
}
});
}
Upvotes: 2