FULLCALENDAR: display events from 2 sources - javascript

I use one source from PHP and it's work thine ! (i'm on fullcalendar v3)
> $('#calendar').fullCalendar({
events: {
url: myevents.php,
type: 'GET',
data: {
param: parametreFilter
},
},
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
lazyFetching: false,
editable: true,
droppable: true, ...
Now i would like to add events from another source. A gouvernemental API that display holidays. So i tried a lot of things and nothing works:
$('#calendar').fullCalendar({
eventSources:[
// your event source
{
url: 'https://calendrier.api.gouv.fr/jours-feries/metropole.json',
type: 'GET',
},
{
url: myevents.php,
type: 'GET',
data: {
param: parametreFilter
}
},
],
eventDataTransform:function(eventData){
console.log("YEP: " + JSON.stringify(eventData)); /* I tried this but the source from API never come in that function */
return eventData;
},
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
lazyFetching: false,
editable: true,
droppable: true,
dragScroll: true,
defaultView: 'agendaWeek',...
I saw this too: https://codepen.io/acerix/pen/EQePxq?editors=0010 But i can't apply it to my example.
I forgot something: I wrote a function to format the events from API, but i think that when i use it, the fullcalendar render is already finish before i get the events from API and reformat them. So its never displayed.
myholidays = []
function getHolidays(url) {
fetch(url)
.then(function(res) {
if (res.ok) {
return res.json().then(function(days) {
/*console.log(jours)*/
let i = 0
let holidays = []
for (const day in days) {
/*console.log(`${day}: ${days[day]}`);*/
holidays.push({ "title": days[day], "start":day+'T00:00:00', "allDay": true})
i++
}
myholidays.push.apply(feries,joursferies)
$('#calendar').fullCalendar( 'refetchEvents' );
})
}
else{
console.log("Error")
}
})
.catch(function(err) {
alert("Error: " + err)
});
}
Can you please help ?

The data at https://calendrier.api.gouv.fr/jours-feries/metropole.json is not an array containing objects in fullCalendar's event format so it will never display them.
You need to use the events-as-a-function option to download the data via your own AJAX request, and then process it into the correct format:
Your attempt above had one or two little mistakes in it, and also doesn't actually insert anything to the calendar, but it was a useful basis for a working solution:
eventSources: [
function (start, end, timezone, callback) {
fetch("https://calendrier.api.gouv.fr/jours-feries/metropole.json")
.then((response) => response.json())
.then(function (data) {
let holidays = [];
for (const day in data) {
holidays.push({
title: data[day],
start: day,
allDay: true
});
}
callback(holidays);
});
},
{
url: "myevents.php",
type: "GET",
data: {
param: parametreFilter
}
}
]
Demo: https://codepen.io/ADyson82/pen/eYvzqOp?editable=true&editors=001

Related

Fullcalendar: how to show multiple resources with multiple events

I am trying to use the Fullcalendar where I need to show multiple resources with respective multiple events. The same source may have more events, including the situation of overbooking.
In the front-end I use Ajax to retrieve the datas for the resources and the events separately.
The following is my code; but it does not work. It fetches the resources and the events, shows the resources but unable to show the respective events.
How can I do it? Thanks a lot.
var calendar = new FullCalendar.Calendar(calendarEl, {
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
plugins: [ 'interaction', 'resourceTimeline' ],
timeZone: 'Europe/Rome',
defaultDate: today,
locale: 'it',
views: {
timelineFourDays: {
type: 'timeline'
//,duration: { months: 4 }
}
},
defaultView: 'resourceTimelineMonth',
lang: 'it',
aspectRatio: 1.5,
header: {
left: 'prev,next',
center: 'title',
right: 'resourceTimelineDay,resourceTimelineWeek,resourceTimelineMonth,resourceTimelineYear'
},
footer: {
left: 'prev,next',
center: 'title',
right: 'resourceTimelineDay,resourceTimelineWeek,resourceTimelineMonth,resourceTimelineYear'
},
resourceAreaWidth: '30%',
resourceLabelText: 'IMPIANTI',
resourceGroupField: 'nome_tipologia',
resourceOrder: 'id',
resourcesInitiallyExpanded: true,
resourceText: 'title',
refetchResourcesOnNavigate: true,
resourceColumns: [
{
labelText: 'IMPIANTO',
field: 'id_impianto',
width: '5%'
},
{
labelText: 'IDENTIFICATIVO',
field: 'impianto_codifica',
width: '15%'
}
,
{
labelText: 'COMUNE',
field: 'nome_comune',
width: '15%'
},
{
labelText: 'ARTICOLO',
field: 'nome_articolo',
width: '15%'
}
],
resources:{
url: '/listallimpiantos',
method: 'get',
_token: CSRF_TOKEN
},
resourceRender: function(renderInfo) {
renderInfo.el.style.backgroundColor = 'green';
renderInfo.el.style.color = '#ffffff';
},
eventSources:{
url: '/listimpiantosperofferta',
method: 'get',
_token: CSRF_TOKEN,
resourceIds:'title'
},
eventRender: function(event, element) {
$(element).tooltip({title: event.title});
if (event.statovendita == 'VENDUTO') {
element.css("background-color", '#378006');
}
if (event.statovendita == 'OPZIONATO') {
element.css("background-color", '#FFA500');
}
},
eventColor: '#378006',
eventBackgroundColor: event.color,
editable: true,
eventStartEditable: true,
eventResizableFromStart: true,
eventDurationEditable: true,
eventResize: function(info) {
alert("Per il cliente " + info.event.title + " dal " + info.event.start.toISOString() + " al " + info.event.end.toISOString());
if (!confirm("Confermi?")) {
info.revert();
} else {
alert('Aggiornamento sul db!');
}
},
selectable: true,
selectAllow: function(select) {
return moment().diff(select.start) <= 0
},
});
}
});
calendar.render();
});
Your eventSources definition is incorrect.
The documentation for eventSources it states that you must provide an array for this option. However, you have provided an object instead.
Since you are only providing one event source, you can either
a) change eventSources to events (because that option will accept a single object), i.e.
events: {
url: '/listimpiantosperofferta',
method: 'get',
_token: CSRF_TOKEN,
resourceIds:'title'
},
or
b) give eventSources an array containing a single item:
eventSources: [{
url: '/listimpiantosperofferta',
method: 'get',
_token: CSRF_TOKEN,
resourceIds:'title'
}],
The other issue you might have is a similar data-type error: The resourceIds option of the event source object expects an array (again you should check the documentation carefully), not a string.
So again to fix that you can either a) use the singular resourceId option instead:
resourceId: 'title'
or continue to use resourceIds but give it an array containing a single item:
resourceIds: ["title"]
Always remember to study the documentation closely and ensure you're matching the relevant syntax, data types, option names etc. Since JavaScript doesn't have compile-time type checking it's easy to overlook this kind of issue, and it will also often fail silently. That's why you have to pay close attention to examples and specifications beforehand.

Get events from Google calendar and database to appear in fullcalendar

I am trying to show events from entity database and from a public google calendar.
I have tried all of the options shown on Stack Overflow to no avail. I can get events to load on two different calendars on different pages using the examples on google calendar example (github)
and database example (youtube)
However I can not get them to load on the same calendar on a single html page. I am using an MVC5 app on vs 2017.
I am just a hobbyist and not a qualified coder so any help much appreciated.
here's how I am getting the an event from the database:
$(document).ready(function () {
var events = [];
var selectedEvent = null;
FetchEventAndRenderCalendar();
function FetchEventAndRenderCalendar() {
events = [];
$.ajax({
type: "GET",
url: "/home/ListEvents",
success: function (data) {
$.each(data, function (i, v) {
events.push({
eventID: v.EventID,
title: v.Subject,
description: v.Description,
start: moment(v.Start),
end: v.End != null ? moment(v.End) : null,
color: v.ThemeColor,
allDay: v.IsFullDay
});
})
GenerateCalender(events);
},
error: function (error) {
alert('failed');
}
})
}
and here's how I am getting event from the database and Google (the following of the above code):
function GenerateCalender(events) {
$('#calender').fullCalendar('destroy');
$('#calender').fullCalendar({
contentHeight: 400,
defaultDate: new Date(),
timeFormat: 'h(:mm)a',
plugins: ['interaction', 'dayGrid', 'list', 'googleCalendarPlugin'],
header: {
left: 'prevYear,prev,next,nextYear today',
center: 'title',
right: 'listMonth,month,basicWeek,basicDay'
},
eventLimit: true,
eventColor: '#378006',
eventRender: function (event, element, view) {
element.find('#txtSubject');
element.find('#txtSubject');
element.find('.fc-list-item-title');
element.find('.fc-list-item-title');
//return ['all', event.conferencier].indexOf($('#filter-conferencier').val()) >= 0;
return ['All events', event.title].indexOf($('#numero').val()) >= 0 || ['', event.color].indexOf($('#color').val()) >= 0;
},
googleCalendarApiKey: '*************************',
eventSources: [
events,
{
googleCalendarId:'blah...blah'
}
],
eventClick: ETC ETC
});
I also tried adding those lines:
$('#calendar').fullCalendar('addEventSource', 'https://calendar.google.com/calendar/embed?src=BLAH.......BLAH');
}
})

FullCalendar v3 - Change Event Source on View Change

I'm using FullCalendar v3 (latest) with a PHP backend.
I'm returning a JSON array from the backend broken up into 2 arrays. The first contains event details (a list of orders for the day, with the order# as the title), and the second contains a daily summary (with a sum of orders and work hours as the title). The array looks like this:
{"events":[{"id":709989,"item_no":"ABC123","title":709989,"color":"red","start":"2019-05-14","end":"2019-05-14","allDay":true,"total_hours":3,"remaining_hours":1.5},{"id":709990,"title":709990,"item_no":"ABC345","color":"red","start":"2019-05-15","end":"2019-05-15","allDay":true,"total_hours":5.7,"remaining_hours":3.2}],"summary":[{"id":338823,"title":"Orders: 14\rHours:28.33\rRemaining Hours:13.33","start":"2019-05-14","end":"2019-05-14","allDay":true},{"id":338824,"title":"Orders: 3\rHours:14.2\rRemaining Hours: 12.2","start":"2019-05-15","end":"2019-05-15","allDay":true}]}
There are other properties but these are the basics.
What I'm trying to do is change the array that's used as the event source depending upon which view is selected. I've tried custom event rendering, custom view rendering, multiple event sources (even though it's expensive from a data point-of-view, the # of records aren't so numerous that it greatly effects performance).
The custom view name is customMonth. When this view is selected, I just want to render the summary data (from the summary array). If any of the other views are selected (I'm using basicWeek, month and listWeek), render the events array.
let vname;
$("#calendar").fullCalendar({
defaultDate: new Date(),
defaultView: 'month',
eventRender: function(eventObj, $el, view) {
let n = view.name;
if(n=='customMonth')
{
vname = 'customMonth';
$el.popover({
title: eventObj.title,
content: eventObj.total_hours,
html: true,
trigger: 'hover',
placement: 'auto',
container: 'body'
});
} else {
vname = n;
$el.popover({
title: "Work Order " + eventObj.title,
content: '<strong>Item#</strong>: ' + eventObj.item_no + '<br />' + '<strong>Total Hours</strong>: ' + eventObj.total_hours + '<br />' + '<strong>Remaining Hours</strong>: ' + eventObj.remaining_hours,
html: true,
trigger: 'hover',
placement: 'auto',
container: 'body'
});
}
},
events: function(start, end, timezone, callback){
$.ajax({
url: '/myendpoint',
type: 'POST',
dataType: 'json',
data: {
action: 'get-calendar-summary',
cell: selected_cell
},
success: function(data) {
let events = [];
if(vname=='customMonth') {
obj = data.summary;
$(obj).each(function() {
events.push({
id: $(this).attr('id'),
title: $(this).attr('title'),
start: $(this).attr('dept_due_dt'),
end: $(this).attr('dept_due_dt'),
total_hours: $(this).attr('total_hours'),
remaining_hours: $(this).attr('remaining_hours'),
order_count: $(this).attr('day_order_count'),
has_late_order: $(this).attr('has_late_order'),
allDay: true,
earliest_date: $(this).attr('earliest_date')
});
});
} else {
obj = data.event_results;
$(obj).each(function() {
events.push({
id: $(this).attr('id'),
color: $(this).attr('color'),
title: $(this).attr('title'),
start: $(this).attr('start'),
end: $(this).attr('end'),
earliest_date: $(this).attr('earliest_date'),
item_no: $(this).attr('item_no'),
total_hours: $(this).attr('total_hours'),
remaining_hours: $(this).attr('remaining_hours')
});
});
}
callback(events);
},
error: function(err) {
console.log(err);
}
});
},
views: {
customMonth: {
type: 'month',
buttonText: 'overview'
}
},
viewRender: function(view, el) {
let lastview;
if(view.name=='customMonth') {
if(lastview == 'customMonth') {
return false;
} else {
view.unrenderDates();
view.renderDates();
$("#calendar").fullCalendar('rerenderEvents');
}
lastview = 'customMonth';
} else {
if(lastview=='customMonth') {
view.unrenderDates();
view.renderDates();
$("#calendar").fullCalendar('rerenderEvents');
}
lastview = view.name;
}
},
header: {
left: 'prev,next',
center: 'title',
right: 'basicWeek,month,listWeek,customMonth'
},
themeSystem: 'bootstrap3',
timeZone: false,
weekends: false,
//tried with and without lazyFetching
lazyFetching: true
});
I'd appreciate any guidance. I've searched StackOverflow (this seems like the closest, but I followed exactly and it didn't work (switching out viewDisplay for viewRender)), Github, and all other sources I can think of.
Here a simplified example of what you are trying to achieve (I hope I well understand your problem) :
HTML :
<div id='calendar'></div>
Javascript :
$(document).ready(function() {
var ev1 = {"events":[{"id":709989,"item_no":"ABC123","title":'Event from source 1',"color":"red","start":"2019-05-14","end":"2019-05-14","allDay":true,"total_hours":3,"remaining_hours":1.5}]};
var ev2 = {"events":[{"id":709989,"item_no":"ABC123","title":'Event from source 2',"color":"blue","start":"2019-05-14","end":"2019-05-14","allDay":true,"total_hours":3,"remaining_hours":1.5}]};
$('#calendar').fullCalendar({
defaultDate: new Date(),
defaultView: 'month',
viewRender: function(view) {
if(view.type === 'basicWeek') {
$('#calendar').fullCalendar( 'removeEventSource', ev1 );
$('#calendar').fullCalendar( 'addEventSource', ev2 );
return;
}
},
header: {
left: 'prev,next',
center: 'title',
right: 'basicWeek,month,listWeek,customMonth'
},
});
$('#calendar').fullCalendar( 'addEventSource', ev1 );
});
And the codepen to try it.
It uses the callback function viewRender() to detect when a view change and addEventSource()/removeEventSource() to change the data. So when you change the view from month to week it will change the source events.

Throwing Error in javascript for loop

Hi I'm using Javascript for loop to generate a string on looping C# list but I'm getting Error
Error 4 The name 'eventList' does not exist in the current context
My complete code is here
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
type: 'POST',
dataType: 'json',
contentType: 'application/json',
url: 'ProjectedYieldCalender.aspx/GetData',
data: '{}',
success:
function (data) {
var eventList = data.d;
alert(eventList.length);
// eventList = demo(eventList);
initCalendar(eventList);
}
});
});
function initCalendar(eventList) {
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,basicWeek,basicDay'
},
//defaultDate: '2014-08-12',
editable: true,
eventLimit: true, // allow "more" link when too many events
events: [
<% for (var i = 0; i < eventList.count ; i++) { %>
{
title : eventList[<%=i%>].name,
start : eventList[<%=i%>].date
}
<% }%>
]
});
}
</script>
Cany any one please let me know where am I doing mistake and please let me know how to use the count of list in for loop . I'm getting proper result if I place some static value in for loop like 'i<5' in stead of 'i < eventList.Count'
You have to do like this. You are trying to access javascript array in asp.net code so it gives you that error.
function initCalendar(eventList) {
var events = [];
for(var i=0;i<eventList.length;i++)
{
events.push({ title : eventList[i].name , start: eventList[i].date });
}
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,basicWeek,basicDay'
},
//defaultDate: '2014-08-12',
editable: true,
eventLimit: true, // allow "more" link when too many events
events: events
});
}

FullCalendar load events from JSON feed on viewRender

FullCalendar v2.2.5, I want to use my JSON generating script to pull data only for the visible area of the calendar as mentioned in a few other questions.
$(document).ready(function() {
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,basicWeek,basicDay',
defaultAllDay: true,
},
lazyFetching: false,
defaultDate: '2015-01-06',
editable: false,
eventLimit: 10,
weekMode: 'liquid',
dayPopoverFormat: 'DD/MM/YYYY',
//events: {
// url: 'instant-tools.cgi',
// type: 'POST',
// data: {
// events: 1,
// pending: 1,
// from: '2014-01-01',
// to: '2016-12-31',
// }
// },
viewRender: function(view, element) {
var events_slice = new Object();
events_slice.eventSources = [
{
url: 'instant-tools.cgi',
type: 'POST',
data: { events: 1, pending: 1, from: '2014-01-01', to: '2016-12-31' }
}
];
$('#calendar').fullCalendar('addEventSource', events_slice);
//$('#calendar').fullCalendar('renderEvents');
},
eventClick: function(calEvent, jsEvent, view) {
alert(calEvent.title + "n" + calEvent.start.format('DD/MM/YYYY') + " to " + calEvent.end.format('DD/MM/YYYY'));
},
});
});
The commented out events definition works (when I use it) but the viewRender one does not. Before you ask viewRender does get triggered. I get no errors in the console and no events displayed. My script is not called at all. I know I have the dates hardcoded right now but I will use view.intervalStart and view.intervalEnd once I verify I get a similar result. Having $('#calendar').fullCalendar('renderEvents'); in there makes no difference, also toggling lazyFetching does not make a difference. Not a JS coder so I hope I'm just being silly somewhere.
in the event property you need to call the function
$(document).ready(function() {
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,basicWeek,basicDay',
defaultAllDay: true,
},
lazyFetching: false,
defaultDate: '$today',
editable: false,
eventLimit: 10,
weekMode: 'liquid',
dayPopoverFormat: 'DD/MM/YYYY',
events: function(start, end, timezone, callback) {
$.ajax({
url: 'instant-tools.cgi',
data: {
events: 1,
pending: 1,
from: '2014-01-01',
to: '2016-12-31',
},
success: function(doc) {
var obj = jQuery.parseJSON(doc);
var events = [];
$.each(obj, function(index, value) {
events.push({
id: value['id'],
//all data
});
//console.log(value)
});
callback(events);
},
error: function(e, x, y) {
console.log(e);
console.log(x);
console.log(y);
}
});
},
eventClick: function(calEvent, jsEvent, view) {
alert(calEvent.title + "n" + calEvent.start.format('DD/MM/YYYY') + " to " + calEvent.end.format('DD/MM/YYYY'));
},
});
});

Categories

Resources