rerender on fullcalendar.io removeing all events - javascript

I am not sure how to approach fullcalender.io. As I will be refreshing the calender, I thought I would return the calendar object like this.
var calendar = function (eventsObj) {
console.log(eventsObj);
return new FullCalendar.Calendar(document.getElementById("calendar"), {
plugins: ['interaction', 'dayGrid', 'timeGrid'],
defaultView: 'dayGridMonth',
defaultDate: new Date().getDate(),
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
events: eventsObj
});
}
I did it this way because I need to refresh all my events inside a bootstrap modal.
When Modal is shown I recall this function.
$("#assignModal").on("shown.bs.modal", function () {
calendar(globalEvents).rerenderEvents();
Here globalEvents is an array with all the events.
I initially render the calendar like this
window.onload = function () {
calendar(globalEvents).render();
};
Issue is that the calendar renders but It does not have any events whereas if I just render the calendar, it keeps all the events. I checked on their docs, they have different features in different versions. Any ideas? please?

So basically according to the v4 guides.
calendar.getEventSources().forEach(function (item) {
item.remove();
});
calendar.addEventSource(globalEvents);
This is how you would have to remove the events and render new ones. Here globalEvents is just an array I use to keep track of my refreshed events.

you can do something like below just remove old events attach new events and rerenderevents
below is some APIS which will help you
//remove old data
$('#fullCalendar').fullCalendar('removeEvents');
//Getting new event json data
$("#fullCalendar").fullCalendar('addEventSource', response);
//Updating new events
$('#fullCalendar').fullCalendar('rerenderEvents');
//getting latest Events
$('#fullCalendar').fullCalendar( 'refetchEvents' );
//getting latest Resources
$('#fullCalendar').fullCalendar( 'refetchResources' );
here is working example

Related

fullCalendar is not a function and events are not rendering

I am trying to run a very basic script that uses the interaction plugin of fullcalendar. I want the users to input events via marking the right date or time in the calendar (select). After marking for example 5th August to 9th August, a prompt would aks for the event title. User types in "vacation" and the script automatically streams the information "from... to" to the event data. But the problem is, after marking the date and typing in the event title, the event does not appear on the calendar.
As long as the site isn't being reloaded, I also cannot mark a new event. In addition, the firefox browser console says fullCalender is not a function. The majority of what is to be found on the web about this issue is that it is most likely the library, which isn't being loaded properly, but according to the browser console its loaded properly indeed. The calendar is visible and I am able to select the date, therefore I do not see the problem. I already put hours into this....
I already tried to change the library from local to CDN, that didn't change no thing.
Here is the code, that I've mixed out of the documentation of fullcalendar and this code pen: https://codepen.io/JSFanatik/pen/QVvxvw
<script type="text/javascript" src='/calendar/fullcalendar/jquery-3.4.1.min.js'></script>
<script type="text/javascript" src='/calendar/fullcalendar/dist/core/main.js'></script>
<script type="text/javascript" src='/calendar/fullcalendar/dist/interaction/main.js'></script>
<script type="text/javascript" src='/calendar/fullcalendar/dist/daygrid/main.js'></script>
<script type="text/javascript" src='/calendar/fullcalendar/dist/timegrid/main.js'></script>
<script type="text/javascript" src='/calendar/fullcalendar/dist/core/locales/de.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
plugins: [ 'interaction', 'dayGrid', 'timeGrid' ],
locale: "de",
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
selectable: true,
navLinks: true,
defaultView: "dayGridMonth",
selectable: true,
selectHelper: false,
editable: true,
eventLimit: false,
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");
},
eventRender: function(event, element) {
element
.find(".fc-content")
.prepend("<span class='closeon material-icons'></span>");
element.find(".closeon").on("click", function() {
$("#calendar").fullCalendar("removeEvents", event._id);
});
},
eventClick: function(calEvent) {
var title = prompt("Change Title:", calEvent.title);
calEvent.title = title;
$("#calendar").fullCalendar("updateEvent", calEvent);
}
});
calendar.render();
});
</script>
I hope you guys can help me with that. I have to say I don't know much about JavaScript, I just have build a website and thought this calendar would be a very useful addition. Thanks!
i've been had same issue, am not sure what cause my problem. but when i check at the debug console it shows "[Violation] 'load' handler took 166ms".
i solve my problem with moving out the code outside method : document.addEventListener('DOMContentLoaded', function() { ..
hope it helps.
Try this:
calendar.refetchEvents();
calendar.render();

How to pass data from controller javascript to view javascript in AngularJS?

I am developing an application in angularJS. I get data from a rest service in the controller. And then I pass that data to the view using $scope. In my view, there is an inpage javascript (I know its a bad practice) and I want to used the data passed in my inpage javascript. Simply using the variable name or {{variable_name}} doesnt work. Can any one give any suggestions?
Here is my code snipper from controller:
$scope.requests = null;
var url = 'my_url';
$http.get(url).then(function(response)
{
$scope.requests = response.data;
if (response.data.status && response.data.message)
{
var status = response.data.status + '!';
var message = response.data.message;
showAlert(status,message);
}
return;
}).catch(function(response)
{
showAlert('danger!','Some error occured. Please try again.');
});
And here is my inpage javascript code:
<script>
$(document).ready(function() {
/*
date store today date.
d store today date.
m store current month.
y store current year.
*/
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
/*
Initialize fullCalendar and store into variable.
Why in variable?
Because doing so we can use it inside other function.
In order to modify its option later.
*/
$('#calendar').fullCalendar({
// put your options and callbacks here
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
defaultView: 'month',
/*
selectable:true will enable user to select datetime slot
selectHelper will add helpers for selectable.
*/
selectable: false,
selectHelper: false,
/*
editable: true allow user to edit events.
*/
editable: false,
/*
eventStartEditable: false doesnt allow the dragging of events
*/
eventStartEditable: false,
/*
eventOverlap: false doesnot allow overlapping of events
*/
eventOverlap: false,
/*
events is the main option for calendar.
for demo we have added predefined events in json object.
*/
/* var events = requests.map(function(obj, index)
{
if (obj.accepted == 'no' ) return false;
return { id : obj.id, start : obj.start, end : obj.end }
})*/
});
});
</script>
<div id='calendar'></div>
Using {{requests}} prints out the data but it CAN NOT be used within the <script> </script> tags. I want to use it with the script tags
In angular you want to include the $window service in your controller, then set a variable on the $window object. The script tag can then check for window.requestsVariable. You are going have to handle the asynchronous nature of the request though, since the request variable will be empty till the request returns.
Further, as andrew.butkus pointed out, you probably don't want to do this. The jquery code could be simplified if you moved it into the linking function of an angular directive for the calendar, IMO.
Declare a global variable as var gloable; outside the controller and inside the controller assign whatever value you want to the declared global variable and then later you can access it inside your Jquery onready function.

selecting a day from UICalendar

I am fairly new to angular I am trying to implement a calendar using ui-calendar. So far I have been able to display a very basic calendar and some events on it.
Now I need to be able to click on a day and display the detailed events on a side tab. I seem to be lost on how to achieve this clicking day thing. This may seems very naive, I thought i'd find the html for each day cell on the calendar, and then it would be as easy as attaching a ng-click to it. But I cant seem to find any template where the html for calendar is. All I can see is the directive, which doesnt help much. I dont understand jquery at all, so I am really struggling to find any answers too.
To sum things up, I just want to know how to make a day on calendar clickable.
Thanks in advance.
code:
$scope.uiConfig = {
calendar: {
height: 450,
editable: true,
header: {
left: 'title',
center: '',
right: 'today prev,next'
},
eventClick: $scope.alertOnEventClick,
eventDrop: $scope.alertOnDrop,
eventResize: $scope.alertOnResize,
eventRender: $scope.eventRender,
dayClick: function(date, jsEvent, view) {
console.log("inside dayClick");
alert('Clicked on: ' + date.format());
var events = myCalendar.fullCalendar('clientEvents', function(event) {
return event.start.isSame(date) || event.end.isSame(date) || date.isBetween(event.start, event.end); // Will return all events starting/ending on this date or overlapping this date
});
}
}
};
In your configuration variable you can add a dayClick callback , in this callback you can do something like this:
dayClick: function( date, jsEvent, view ) {
var events = myCalendar.fullCalendar('clientEvents', function(event) {
return event.start.isSame(date) || event.end.isSame(date) || date.isBetween(event.start, event.end); // Will return all events starting/ending on this date or overlapping this date
});
}
This will return all the events that either are on this day or overlap it.
FullCalendar docs can be found here.

Full Calendar trigger ajax call before event renders on calendar

I'm a bit lost where is the proper place to make this with the Full Calendar documentation and need some fiddle to point me into the right way. When my calendar loads the events, before them show up on the calendar, I need to make a ajax call into a wordpress db which should return a date of a post. Each post is an event on the calendar. Depending on the response of the database, if the post date is in future time than the current time, then the calendar should show this event in an specific color, if it is past or current time it should be another different specific color.
So basically, before each event renders on the calendar I need to trigger an ajax call for each of them and evaluate the data returned to apply them the right color for past/current events and future events.
Someone experienced with Full Calendar could point me a fiddle with an example how is this done within the Full Calendar documentation?
This is the code I went so far. I am looking to stay in the loop with the calendar refetchEvents and be able to fetch with ajax in the background data from the posts of a WordPress website to use it on the next refetchEvents trigger and so on.
$(function () {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
var webData = null; //array() data
$('#calendar-holder').fullCalendar({
eventRender: function(event, element, webData) {
var dataHoje = new Date();
/*
Use webData data taken with ajax on eventAfterAllRender callback option
inside this conditional statements to draw on the event box
colors and text values depending on the status and date of the post returned.
*/
if (event.start < dataHoje && event.end > dataHoje) {
element.css('background-color', '#FFB347');
element.find('.fc-event-inner').append('<span class="fc-event-status">ON AIR</span>');
} else if (event.start < dataHoje && event.end < dataHoje) {
element.css('background-color', '#77DD77');
element.find('.fc-event-inner').append('<span class="fc-event-status">Published</span>');
} else if (event.start > dataHoje && event.end > dataHoje) {
element.css('background-color', '#AEC6CF');
element.find('.fc-event-inner').append('<span class="fc-event-status">Schedued</span>');
}
},
eventAfterAllRender: function () {
webData = '(AJAX CALL TO WEBSITE POSTS I THINK SHOULD GO HERE)';
console.log(webData);
},
eventColor: '#378006',
complete: function() {
},
defaultView: 'basicDay',
googleCalendarApiKey: 'AIzaSyCtEQZsFtsY41kJ1Av5FftgX9kdfkHKH',
events: {
googleCalendarId: 'mywebsite.com_l84tadr5fulc7j0628g3g6oj3k#group.calendar.google.com'
},
header: {
left: 'prev, next',
center: 'title',
right: 'basicDay, basicWeek, month, '
},
lazyFetching: true,
timeFormat: {
agenda: 'h:mmt', // 5:00 - 6:30
'': 'h:mmt' // 7p
},
weekNumbers: false,
lang: 'en',
eventSources: [
{
url: Routing.generate('fullcalendar_loader'),
type: 'POST',
data: {
},
error: function() {
}
}
]
});
});
var refreshRate;
function reloadTime() {
refreshRate = setTimeout(reloadPage, 5000);
}
function reloadPage() {
$("#calendar-holder").fullCalendar("refetchEvents");
reloadTime();
}
$( document ).ready(function() {
reloadTime();
});
Changing the color:
The way you did it works, but the easiest way is to do it in eventDataTransform. Like so:
eventDataTransform: function(eventData){
if(eventData.end.isBefore(moment())){
eventData.color = "black";
}else{
eventData.color = "green";
}
return eventData;
},
Color Demo
Check if event exists
You didn't mention exactly what to do if the database returns false, but I'll assume you don't want nonexistent events rendered.
Since the source for your events is google calendar, this is actually kind of tricky. Normally, you would use the custom events function and do two ajax calls in it (one for the events and one for checking if they are valid). But you can't do this with google cal events.
So instead we will use eventDataTransform and only display the events after we know they exist.
eventDataTransform: function(eventData){
eventData.display = false; //Don't display until we check the server
eventData._uid = idCounter++; //unique ID. Don't need this if they already have unique IDs
ajaxCall(eventData); //check the server (will retroactively update the event to be displayed)
if(eventData.start.isBefore(moment())){ /*...*/ } //colors
return eventData;
},
The top of your eventRender callback should look like:
eventRender: function(event,element){
if(!event.display){ //Render only if the event exists
return false; //return false to stop the event from rendering.
}
/*...your other render code if you have any*/
}
Define your ajaxCall function outside of fullcalendar:
var ajaxCall = function(eventData){
$.get( "ajax/test.html", function( data ) {
setEvent(eventData._uid,data); //data should be a boolean
});
};
var setEvent = function(id,exists){
var fcEvent = $('#calendar').fullCalendar("clientEvents",function(event){ //get the associated event object
if(event._uid === id){
return true;
}
})[0];
if(typeof fcEvent !== "object")$.error("Event id "+id+" doesn't exist!"); //Throw error if it doesn't exist
fcEvent.display = exists; // Store the server response in the event
$('#calendar-holder').fullCalendar("updateEvent",fcEvent); // Updates and re-renders the event
}
JSFiddle Demo (using fake ajax calls)
Some Explanation
Couple of things that might be useful to know:
The word render in fullcalendar refers to actually displaying the events. It's done whenever the view changes (more often than events are fetched from the DB)
Event sources only fetch events when they are needed. They are stored client-side as data that can be rendered as needed.
eventDataTransform is called once after an event source retrieves an event.
So if you put your ajax call in eventAfterAllRender, the ajax call would be done everytime FC decided to render the calendar resulting in more ajax calls that necessary. It also means you would get a delay every time you change the view. It's much better to do it earlier than render-time.

Affecting Fullcalendar today button .fc-today-button

I'm having trouble getting custom controls to work when clicking the 'today' button that is part of Fullcalendar.
All the documentation I can find tells me that Fullcalendar's built-in controls can be affected using two methods:
So, this one works for me when it's applied to previous, next, month, agendaWeek and agendaDay, but not for 'today' (button.fc-today-button):
$('body').on('click', 'button.fc-next-button', function() {
console.log('I Clicked Next');
});
Some documentation also say that this works, although I can't make it do so on any button:
$('.fc-next-button span').click(function(){
console.log('I Clicked Next');
});
Does anyone know why this is and what I'm doing wrong?
Well, you want to affect the "today" button, yet you are adding code for the "next" button. You want to do something like:
$(".fc-today-button").click(function() {
alert('Clicked Today!');
});
This applies a click event to anything with the class "fc-today-button" (that is the class that the Today button will have).
Working example:
$('#fullCal').fullCalendar({
events: [{
title: 'Event 1',
start: moment().add(1, 'h'),
end: moment().add(2, 'h'),
allDay: false
}],
header: {
left: '',
center: 'prev title next today',
right: ''
},
timezone:'local',
defaultDate: '2014-11-15',
editable: false,
eventLimit: false,
firstDay: 6,
defaultView: 'agendaWeek',
});
$(".fc-today-button").click(function() {
alert('Clicked Today!');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.3/moment.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.1.1/fullcalendar.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.1.1/fullcalendar.min.js"></script>
<div id="fullCal"></div>
After investigation and the help of MikeSmithDev (thanks Mike - your help was invaluable), it appears as though the 'today' event only gets triggered if it physically positioned below/after the calendar, the rest of the header controls (button.fc-next-button etc) don't seem to mind where they are physically positioned.
Likely the first function executes before the calendar is finished loading... so it works, there is just no button to bind it to.
I was able to more or less achieve this with a native workaround of sorts. You may utilize the "customButtons" and "headerToolbar" in combination to effectively remove the original today button and replace it with your own which can trigger custom function code upon being clicked.
I'm actually using this with VueJS, but should be equally feasible with Vanilla JS.
// these are the options you can pass when initializing a fullcalendar
customButtons: {
focusButton: {
text: "focus",
click: this.scrollToCurrentDay // this is a vue component function, but you could just as well pass a vanilla JS function
}
},
headerToolbar: { // this effectively removes the original today button and adds our custom button to the header of the calendar
left: '',
center: 'title',
right: 'prev focusButton next'
}
I wanted to do this because I wanted to not only focus the month when today was clicked, but also to scroll the calendar to the day (useful when using small screens like phones).
My custom today button click handler:
scrollToCurrentDay: function(arg) {
let CalendarAPI = this.$refs.calendar.getApi();
CalendarAPI.today();
var todayElement = document.getElementsByClassName('fc-day-today')[0];
var calendarElement = document.getElementsByClassName('fc')[0];
if (todayElement) {
todayElement.scrollIntoView();
} else {
calendarElement.scrollIntoView();
}
},

Categories