fullCalendar: Events aren't shown where expected on the grid - fullcalendar

Looked through the docs, but don't see why the events are placed incorrectly in my node app:
Global.js:
var eventList = [];
document.addEventListener('DOMContentLoaded', function() {
var eventDesc = {};
eventDesc = { title: 'Test', start: '2019-10-22', backgroundColor:'red' }; eventList.push( eventDesc );
eventDesc = { title: 'Test2', start: '2019-10-23T10:00:00', end: '2019-10-23T11:00:00', backgroundColor:'blue' }; eventList.push( eventDesc );
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
defaultView: "timeGridWeek",
height: "auto",
slotDuration: "00:60:00",
events: eventList,
plugins: [ 'dayGrid', 'timeGrid' ]
}
);
calendar.render();
});
Getting the following view (expect the blue event to be at 10 am on the grid, but it's off the grid entirely):
grid view

Related

fullcalendar v5 after edit event render() don't refresh

when i edit a event list, it correctly reload but calendar don't refresh.
if i click in other tab and then return in calendar tab it refresh: problem with bootstrap? This is my function to init calendar
function getCalendar(mydate) {
//Date for the calendar events (dummy data)
var date = new Date()
var d = date.getDate(),
m = date.getMonth(),
y = date.getFullYear()
var calendar = FullCalendar.Calendar;
var calendarEl = document.getElementById('calendar');
var calEv=bindEvents(mydate);
//var calRi=bindResource(mydate);
dCal = new calendar(calendarEl, {
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
timeZone: 'UTC',
height: '100%',
contentHeight: 'auto',
initialView: 'dayGridMonth',
themeSystem: 'bootstrap',
locale: 'it',
//Random default events
//events: 'https://fullcalendar.io/demo-events.json',
//events: bindEvents(mydate),
//events: calEv,
//events: evUrl,
events: function(info, successCallback, failureCallback) {
var evUrl = window.apiurl+'/api/anagrafiche/tourfascecalevents/'+id_entita;
$.ajax(evUrl, {
type: 'GET',
cache: false,
}).done(function(dati) {
dbgConsole("render init ev");
dbgConsole(dati);
ev=bindEvents(dati);
dbgConsole(ev);
successCallback(ev);
}).fail(function(x,s,t) {
alert_error(x);
});
},
//resources: bindResource(mydate),
initialDate: dataIni,
editable : true,
selectable: true,
droppable : false, // this allows things to be dropped onto the calendar !!!
dateClick: function(info) {
dbgConsole(info);//event.setProp( name, value )
var cls=[];
var data_fine = moment(info.dateStr, "YYYY-MM-DD").add(gg_viaggio, 'days').format('YYYY-MM-DD');
if ('undefined' == typeof grpSelected || ''==grpSelected) {
// alert('Cancellazione data: ' + info.dateStr + ' !');
var reqUrl = window.apiurl+'/api/anagrafiche/tourfasce/'+id_entita;
$.ajax(reqUrl, {
type: 'DELETE',
cache: false,
data: {
id_gruppo: id_gruppo,
id_entita: id_entita,
MM_delete: 'form_fascedel',
data_inizio: info.dateStr
}
}).done(function(dati) {
window.tables['FasceTable'].setData();
dbgConsole("render");
//$('#h-tab').trigger('click');
//$('#dati-fasce-tab').trigger('click');
dCal.render();
//dCal.updateSize();
}).fail(function(x,s,t) {
alert_error(x);
});
} else {
// alert('Imposta data: ' + info.dateStr + ' in gruppo "'+grpSelected+'" !');
var reqUrl = window.apiurl+'/api/anagrafiche/tourfasce/'+id_entita;
$.ajax(reqUrl, {
type: 'PUT',
cache: false,
data: {
id_gruppo: id_gruppo,
id_entita: id_entita,
MM_update: 'form_fasceupd',
data_inizio: info.dateStr,
nome_periodo: grpSelected,
data_fine: data_fine
}
}).done(function(dati) {
window.tables['FasceTable'].setData();
dbgConsole("render");
//$('#h-tab').trigger('click');
//$('#dati-fasce-tab').trigger('click');
dCal.render();
//dCal.updateSize();
}).fail(function(x,s,t) {
alert_error(x);
});
}
// alert('Gruppo: ' + id_gruppo + ' - Entita: "'+id_entita+ ' - Giorni: "'+gg_viaggio+'" !');
//dCal.setOption('initialDate', '2021-06-01');
//dCal.render();
},
/*
eventClick: function(calEvent, jsEvent, view) {
var testo='';
testo=testo+'Servizio: ' + calEvent.title_serv+'\n';
testo=testo+'Inizio: ' + calEvent.start.format()+'\n';
testo=testo+'Fine: ' + calEvent.end.format()+'\n';
testo=testo+'Descrizione: ' + calEvent.title+'\n';
alert(testo);
}
*/
});
//dCal.render();
dbgConsole("Cal:")
dbgConsole(dCal);//event.setProp( name, value )
}
and this is activation
$('#dati-fasce-tab').on('shown.bs.tab', function (event) {
dCal.render();
})
after 'dateClick' events are modified and reloaded but calendar not update view
P.S.: all events are type 'background'
Already exists any different method to refresh?
We are a problem to refresh on load calendar in hidden area, any idea?
First of all, you need to render the fullcalendar element inside the initialize function.
function getCalendar(mydate) {
...
dCal = new calendar(calendarEl, {
});
dCal.render();
}
After that, you need to use refetchEvents function while an event like changing tab or save an event is firing.
https://fullcalendar.io/docs/Calendar-refetchEvents
dCal.refetchEvents();
You could face into an issue like dCal is undefined, then you need to add some handling like
if (typeof dCal !== 'undefined') {
dCal.refetchEvents();
}

FullCalender 5 Unable to render dynamic events & resources

I am trying to render events and resources which are stored in a database. I can get the calendar to render with predefined data for events and resources, however when I push data into the array's, the new objects do not appear when the calendar is rendered.
This is the JS code I am using to obtain the data and render the calendar;
function GetCalenderDetails() {
$.ajax({
url: 'myapiendpoint',
type: 'GET',
success: function (response) {
$.each(response.bookedServices, function (i, v) {
services.push({
id: v.id,
title: v.title
});
});
console.log(JSON.stringify(services));
$.each(response.userBookings, function (i, v) {
bookings.push({
id: v.id,
resourceId: v.resourceId,
title: v.title,
start: v.start,
allDay: v.allDayFlag
});
});
console.log(JSON.stringify(bookings));
calendar.render();
},
error: function (error) {
console.log(error);
}
});
}
var bookings = new Array({ id: '1', resourceId: 'a', title: 'Meeting', start: '2021-03-14', allDay: true });
var services = new Array({ id: 'a', title: 'Room A' });
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
timeZone: 'UTC',
initialView: 'resourceTimelineDay',
aspectRatio: 1.5,
headerToolbar: {
left: 'prev,next',
center: 'title',
right: 'resourceTimelineDay,resourceTimelineWeek,resourceTimelineMonth'
},
editable: true,
resourceAreaHeaderContent: 'Resources',
resources: services,
events: bookings
});
GetCalenderDetails();
The following is the console output of the 'services' and 'bookings' variables after the GetCalenderDetails function is executed;
Resources Output
[{"id":"a","title":"Room A"},{"id":"b","title":"Room B"}]
Events Output
[{"id":"1","resourceId":"a","title":"Meeting","start":"2021-03-14","allDay":true},
{"id":"2","resourceId":"b","title":"Meeting B","start":"2021-03-15","allDay":true}]
The first resource and event will render, however the second item which is pushed into the array from the GetCalenderDetails function do not render.
I am probably missing something very obvious, but I am not seeing it, so another set of eyes might help :)
As suggested by ADyson's comments, here is the solution to my problem just in case anyone else ends up in the same position;
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
timeZone: 'UTC',
initialView: 'resourceTimelineDay',
headerToolbar: {
left: 'prev,next,today',
center: 'title',
right: 'resourceTimelineDay,resourceTimelineWeek,resourceTimelineMonth'
},
editable: true,
resourceAreaHeaderContent: 'Booked Services',
resources: function (info, successCallback, failureCallback) {
$.ajax({
url: 'myapiendpoint',
type: 'GET',
success: function (response) {
var resources = [];
console.log(response);
if (response.status == true) {
$.each(response.bookedServices, function (i, v) {
resources.push({
id: v.id,
title: v.title
});
});
} else {
//Do something
}
return successCallback(resources);
},
error: function (error) {
console.log(error);
}
});
},
events: function (info, successCallback, failureCallback) {
$.ajax({
url: 'myapiendpoint',
type: 'GET',
success: function (response) {
var events = [];
console.log(response);
if (response.status == true) {
$.each(response.userBookings, function (i, v) {
events.push({
id: v.id,
title: v.title,
start: v.start,
allDay: v.allDayFlag
});
});
} else {
//Do something
}
return successCallback(events);
},
error: function (error) {
console.log(error);
}
});
}
});
calendar.render();

onDragStop tells me jsEvent is undefined

I'm trying to make it possible to drag events to an external div and back into the calendar again. However, whenever I drop an event I get TypeError: jsEvent is undefined.
I'm not entirely sure why it is doing this, this should be a valid parameter that is passed to the function of eventDragStop.
I'm using the latest FullCalendar 4.
Here is my code
// Load the CSS stuff
import {Tooltip} from "bootstrap";
require('#fortawesome/fontawesome-free/css/fontawesome.min.css');
require('#fortawesome/fontawesome-free/css/brands.min.css');
require('#fortawesome/fontawesome-free/css/solid.min.css');
require('../css/app.scss');
// Load the JS stuff
let $ = require('jquery');
require('bootstrap');
require('./libs/navbar.js');
require('jquery-ui/ui/widgets/draggable');
import apiclient from "./libs/apiclient";
import { Calendar } from '#fullcalendar/core';
import dayGridPlugin from '#fullcalendar/daygrid';
import timeGridPlugin from '#fullcalendar/timegrid';
import interactionPlugin from '#fullcalendar/interaction';
import bootstrapPlugin from '#fullcalendar/bootstrap';
// $(document).ready(function () {
//
// });
document.addEventListener('DOMContentLoaded', () => {
/* initialize the external events
-----------------------------------------------------------------*/
$('#external-events .fc-event').each(function() {
// store data so the calendar knows to render an event upon drop
$(this).data('event', {
title: $.trim($(this).text()), // use the element's text as the event title
stick: true // maintain when user navigates (see docs on the renderEvent method)
});
// make the event draggable using jQuery UI
$(this).draggable({
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0 // original position after the drag
});
});
let calendarEl = document.getElementById('calendar-holder');
let calendar = new Calendar(calendarEl, {
views: {
jira: {
type: 'dayGridWeek',
duration: {months: 3},
buttonText: 'Jira'
}
},
defaultView: 'jira',
themeSystem: 'bootstrap',
editable: true,
droppable: true,
firstDay: 1,
contentHeight: 'auto',
weekNumbersWithinDays: true,
weekNumbers: true,
eventSources: [
{
url: "/fc-load-events",
method: "POST",
extraParams: {
filters: JSON.stringify({})
},
failure: () => {
// alert("There was an error while fetching FullCalendar!");
},
},
],
header: {
left: 'prev,next today',
center: 'title',
right: 'jira,dayGridMonth,timeGridWeek',
},
plugins: [ bootstrapPlugin, interactionPlugin, dayGridPlugin, timeGridPlugin ], // https://fullcalendar.io/docs/plugin-index
timeZone: 'UTC',
eventRender: function(info) {
var tooltip = new Tooltip(info.el, {
title: info.event.title+'<br>'+info.event.extendedProps.assignee,
placement: 'top',
trigger: 'hover',
container: 'body',
html: true
});
},
dragRevertDuration: 0,
drop: function() {
// is the "remove after drop" checkbox checked?
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the "Draggable Events" list
$(this).remove();
}
},
eventDragStop: function( event, jsEvent, view ) {
if(isEventOverDiv(jsEvent.clientX, jsEvent.clientY)) {
$('#calendar-holder').calendar('removeEvents', event._id);
var el = $( "<div class='fc-event'>" ).appendTo( '#external-events-listing' ).text( event.title );
el.draggable({
zIndex: 999,
revert: true,
revertDuration: 0
});
el.data('event', { title: event.title, id :event.id, stick: true });
}
}
});
calendar.render();
let isEventOverDiv = function(x, y) {
var external_events = $( '#external-events' );
var offset = external_events.offset();
offset.right = external_events.width() + offset.left;
offset.bottom = external_events.height() + offset.top;
// Compare
if (x >= offset.left
&& y >= offset.top
&& x <= offset.right
&& y <= offset .bottom) { return true; }
return false;
}
});
I figured out that the jsEvent is now located in event.jsEvent. This is where I can get the position from now.

bootstrap3 pretty-fullcalendar meteor not reactive in blaze

I'm using a bootstrap3 pretty-fullcalendar in a project and pre blaze, when I changed some properties of an event (such as color) it was immediately reflected in the display on the calendar. Now, when I change the attribute, I have to reload the calendar manually to have the change show up.
I'm instantiating the calendar in the template render function as
Template.packLayout.rendered = function(){
$('#calendar').fullCalendar({
//dayClick:function( date, allDay, jsEvent, view ) {
// Requests.insert({title:'Request',start:date,end:date,color:'red',className:'todo'});
// Session.set('lastMod',new Date());
//},
eventClick:function(reqEvent,jsEvent,view){
Session.set('editingReqEvent',reqEvent.id);
Session.set('showEditEvent',true);
},
eventDrop:function(reqEvent){
Requests.update(reqEvent.id, {$set: {start:reqEvent.start,end:reqEvent.end}});
Session.set('lastMod',new Date());
},
events: function(start, end, callback) {
var events = [];
reqEvents = Requests.find();
reqEvents.forEach(function(evt){
event = {id:evt._id,title:evt.title,start:evt.start,end:evt.end,color:evt.color};
events.push(event);
})
callback(events);
},
editable:true,
weekMode: 'liquid'
});
}
Has something changed that would make this happen?
Here is how i managed to get it working:
1) keep your calendar code as per "rendered"
Template.calendar.rendered = function () {
console.log('Calendar - running redered');
Session.set('calendarTemplateRendered', true);
var entries = Calendar.find().fetch(),
$calendar = $('#calendar');
$calendar.html('').fullCalendar({
header: {
left: '',
center: '',
right: ''
},
contentHeight: 1100,
defaultDate: '2014-01-12',
defaultView: 'agendaWeek',
editable: true,
selectable: true,
selectHelper: true,
select: function (start, end) {
var title = prompt('Event Title:');
var eventData;
if (title) {
eventData = {
title: title,
start: start,
end: end
};
$('#calendar').fullCalendar('renderEvent', eventData, true); // stick? = true
}
$('#calendar').fullCalendar('unselect');
},
events: entries
});
Add a autorun:
Deps.autorun(function () {
if (Session.equals('calendarTemplateRendered', false) ||
!calendarSubs.ready() ||
typeof Calendar === 'undefined') {
console.log('exiting because there is no objects to process');
return;
}
console.log('trying to autorun');
var entries = Calendar.find().fetch(),
$calendar = $('#calendar');
$calendar.fullCalendar('removeEvents');
$calendar.fullCalendar('addEventSource', entries);
$calendar.fullCalendar('rerenderEvents');
}
Blaze will do the rest for you - (redraw the UI properly). Now you can just modify your Calendar subscription as you like and it will work perfectly.

Fetching all GoogleCalendar Events before FullCalendar has loaded

I currently am using Adam Shaw's jQuery Calendar 'FullCalendar' and am experiencing significant delays in the calendar rendering. In short, the page appears, 1 second passes, the Calendar pops in, another second passes, and then the events populate the page, here. Is there a way to only fetch a certain number of events behind and before today's date? Or even loading the calendar immediately would be an improvement. I am also using Craig Thompson's qTip2.
Javascript
<script type=text/javascript>
// Setup FullCalendar
jQuery(document).ready
(function() {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
var tooltip = $('<div/>').qtip({
id: 'fullcalendar',
prerender: true,
content: {
text: ' ',
title: {
},
},
events: {
render: function(event, api) {
var elem = api.elements.bgiframe;
}
},
position: {
my: 'bottom center',
at: 'top center',
target: 'event',
viewport: $(window),
adjust: {
mouse: false,
scroll: true,
method: 'shift',
resize: true
}
},
show: {
modal: {
on: false,
blur: true,
stealfocus: false
}
},
hide: false,
style: 'qtip-bootstrap'
}).qtip('api');
$('#fullcalendar').fullCalendar({
eventSources: ["https://www.google.com/calendar/feeds/emailaddresshere/public/basic",
"http://www.google.com/calendar/feeds/usa__en%40holiday.calendar.google.com/public/basic"],
header: {
left: 'title',
center: '',
right: 'today prev,next'
},
selectable: true,
eventClick: function(data, event, view) {
var content = '<h3>'+data.title+'</h3>' +
'<p><b>Start:</b> '+data.start+'<br />' +
(data.end && '<p><b>End:</b> '+data.end+'</p>' || '');
tooltip.set({
'content.text': content
})
.reposition(event).show(event);
},
dayClick: function() { tooltip.hide() },
eventResizeStart: true,
eventDragStart: false,
viewDisplay: function() { tooltip.hide() }
});
}());
</script>

Resources