When I initially load my calendar, it loads the calendar with all of the headings/buttons, but not the actual calendar itself. I have to press the "today" button for it to load the calendar on today's week. Any idea how to get it to do this on initial load? If it helps, here's the code I'm using. I'm pretty clueless as to what's happening here, I inherited this piece of work off someone else, this is my first time looking at this fullcalender addon.
function calendar() {
//gets saved events
var sourceFullView = { url: '/Calendar/GetDiaryEvents/' };
var sourceSummaryView = { url: '/Calendar/GetDiarySummary/' };
var CalLoading = true;
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
defaultView: 'agendaWeek',
editable: true,
allDaySlot: false,
selectable: true,
slotMinutes: 15,
events: '/Calendar/GetDiaryEvents/',
eventClick:
function(calEvent) {
//modal located at the bottom of the page
var modalElementId = $("#modal");
//url located in the Calendar controller. CalEvent Id referes to event id
var url = GetUrlPath() + '/Calendar/OpenDetailsModal?id=' + calEvent.id;
var appointmentId = calEvent.id;
//These are defined at the top of the page
$('#DiaryEventID').val(appointmentId);
$('#DiaryEventID').val("");
var viewModel = new CalenderViewModel(appointmentId);
showEditModal(null, viewModel, url, modalElementId);
$('.modal-backdrop').removeClass('modal-backdrop');
},
eventDrop: function(event, dayDelta, minuteDelta, allDay, revertFunc) {
if (confirm("Confirm move?")) {
UpdateEvent(event.id, event.start);
} else {
revertFunc();
}
},
eventResize: function(event, dayDelta, minuteDelta, revertFunc) {
if (confirm("Confirm change appointment length?")) {
UpdateEvent(event.id, event.start, event.end);
} else {
revertFunc();
}
},
dayClick: function(date, allDay, jsEvent, view) {
$('#eventTitle').val("");
setTimeout(ShowClientEventModal(), 100);
for (i = 0; i < 2; i++) {
if (date != "") {
$('#eventClientDate').val($.fullCalendar.formatDate(date, 'dd/MM/yyyy'));
$('#eventClientTime').val($.fullCalendar.formatDate(date, 'HH:mm'));
$("#eventClientDate").datepicker({ dateFormat: 'dd/mm/yy' });
}
}
},
viewRender: function(view, element) {
if (!CalLoading) {
if (view.name == 'month') {
$('#calendar').fullCalendar('removeEventSource', sourceFullView);
$('#calendar').fullCalendar('removeEvents');
$('#calendar').fullCalendar('addEventSource', sourceSummaryView);
} else {
$('#calendar').fullCalendar('removeEventSource', sourceSummaryView);
$('#calendar').fullCalendar('removeEvents');
$('#calendar').fullCalendar('addEventSource', sourceFullView);
}
}
}
});
CalLoading = false;
}
Bit more info, this is strange, but when I press F12 on the browser to go into developer tools, then calendar suddenly renders as if I pressed the today button. But when I go into the calendar page with the debugger already open, it renders the headers without the calendar content. What the hell is going on?
I would suggest you try removing all code related to CalLoading, so remove the variable assignment from the top, remove the entire viewRender function, and remove the variable assignment to false at the bottom. It looks like some type of function for not displaying the events until they are all loaded, or something like that, and my guess is its not working properly.
Edit: It looks like the function swaps out event sources to sourceSummaryView on month view, and sourceFullView on any other, so removing this will still have the calendar default to the sourceFullView, but I do not know the difference of the two so you will just need to try and see how it works.
var CalLoading = true;
viewRender: function(view, element) {
if (!CalLoading) {
if (view.name == 'month') {
$('#calendar').fullCalendar('removeEventSource', sourceFullView);
$('#calendar').fullCalendar('removeEvents');
$('#calendar').fullCalendar('addEventSource', sourceSummaryView);
} else {
$('#calendar').fullCalendar('removeEventSource', sourceSummaryView);
$('#calendar').fullCalendar('removeEvents');
$('#calendar').fullCalendar('addEventSource', sourceFullView);
}
}
}
CalLoading = false;
Related
In my code, I am trying to execute a function that would change the defaultView of my fullCalendar based on the screen size. However, this only executes when a user loads in the screen size that I currently set it to.
I tried to view it on another screen to see if my else or : would execute and it did, but it only works once you refresh it on screen you are in. I would go to my developer tools/inspect element and drag the window to my desire screen size, but it still wouldn't execute.
Is there an improvement I can do in my code that I code or something that I am missing? I would love to learn from this as this is my first time trying out something crazy with the fullCalendar.
$(document).ready(function () {
$('#calendar').fullCalendar({
defaultView: $(window).width() < 765 ? 'basicDay':'agendaWeek',
header: {
left: "prev,next today",
center: "title",
right: "listMonth, month,agendaWeek,agendaDay",
},
displayEventTime: false,
editable: false,
eventRender: function(calEvent, element, view) {
// Check if the checkboxes already are added to FullCalendar
var checkboxPresent = false;
if( $('.calendar').find(".checkboxContainer").length == 1 ){
checkboxPresent = true;
}
if ( calEvent.title == "Title 1" ) {
element.css('background-color', '#44804C').addClass("normal");
if( checkboxPresent && !$("#normal").is(":checked") ){
element.hide();
}
}
else if (calEvent.title == "Title 2" ) {
element.css('background-color', '#804478').addClass("event");
if( checkboxPresent && !$("#event").is(":checked") ){
element.hide();
}
}
},
events: 'load.php',
});
// Create Checkboxes
var checkboxContainer = $("<div class='mb-3 checkboxContainer'><div class='d-flex flex-row'><label>Normal</label><input type='checkbox' id='normal' class='mx-3' checked></div><div class='d-flex flex-row'><label for='normal'>Event</label><input type='checkbox' id='event' class='mx-3' checked></div></div>");
// Append it to FullCalendar.
$(".fc-toolbar").before(checkboxContainer);
// Click handler
$("#calendar").on("click", "input[type='checkbox']", function(){
if($(this).is(":checked")){
$('#calendar').find("."+$(this).attr("id")).show();
}else{
$('#calendar').find("."+$(this).attr("id")).hide();
}
});
});
You can use this event hook which is triggered whenever the calendar is resized: https://fullcalendar.io/docs/windowResize
$(document).ready(function () {
$('#calendar').fullCalendar({
defaultView: $(window).width() < 765 ? 'basicDay':'agendaWeek',
windowResize: (arg) => {this.changeView($(window).width() < 765 ? 'basicDay':'agendaWeek')},
});
};
You might need to replace this. with a variable assigned to FullCalendar itself, something like:
$(document).ready(function () {
let FC = FullCalendar.Calendar({
defaultView: $(window).width() < 765 ? 'basicDay':'agendaWeek',
windowResize: (arg) => { FC.changeView($(window).width() < 765 ? 'basicDay':'agendaWeek') },
});
$('#calendar') = FC;
};
I have the following function for pulling data from a php json_encode for use in FullCalendar.
eventDrop: function(info) {
$.get( "php/get-events.php", function( data ) {
// data is your result
// Find the value for editable where the event id = the event you are trying to move
rawdata = JSON.parse(data);
editable = rawdata.find(x => x.id === info.event.id).editable;
start= info.event.start.toISOString();
start = moment(info.event.start).format('Y-MM-DD HH:mm:ss');
end= info.event.end.toISOString();
end = moment(info.event.end).format('Y-MM-DD HH:mm:ss');
title = info.event.title;
id = info.event.id;
});
}
I will use very similar code for the eventResize function within fullcalendar, so I would like to extract this part
$.get( "php/get-events.php", function( data ) {
// data is your result
// Find the value for editable where the event id = the event you are trying to move
rawdata = JSON.parse(data);
into it's own function (not 100% sure I'm using the right terminology here?) I seen this answer jQuery - Passing variable within a function to another function about how to pass variables in the global scope, so I tried to move my above code out of eventDrop like so
$.get( "php/get-events.php", function( data ) {
// data is your result
// Find the value for editable where the event id = the event you are trying to move
rawdata = JSON.parse(data);
});
eventDrop: function(info) {
But this gives me an error
Uncaught SyntaxError: Unexpected token '.'
Ideally I would like to do the json extract using the $.get only one time throughout my page, and then reference the rawdata global variable to read the information, is this possible?
My full solution at current is
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var today = moment().day();
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
defaultDate: today,
editable: true,
$.get( "php/get-events.php", function( data ) {
// data is your result
// Find the value for editable where the event id = the event you are trying to move
rawdata = JSON.parse(data);
});
eventDrop: function(info) {
editable = rawdata.find(x => x.id === info.event.id).editable;
start= info.event.start.toISOString();
start = moment(info.event.start).format('Y-MM-DD HH:mm:ss');
end= info.event.end.toISOString();
end = moment(info.event.end).format('Y-MM-DD HH:mm:ss');
title = info.event.title;
id = info.event.id;
if (!confirm("Confirm you want to change " + info.event.title + " to " + info.event.start)) {
info.revert();
}
else{
if(editable === 'Y'){
$.ajax({
url: 'php/calendarupdate.php',
data: 'title=' + info.event.title + '&start='+ start +'&end=' + end + '&id=' + info.event.id ,
type: "POST"
});
}
else{
alert("Can only modify this calendar event if you created it. Please ask the event creator to modify.");
calendar.refetchEvents();
}
}
},
navLinks: true, // can click day/week names to navigate views
dayMaxEvents: true, // allow "more" link when too many events
events: {
url: '/php/get-events.php',
failure: function() {
document.getElementById('script-warning').style.display = 'block'
}
},
loading: function(bool) {
document.getElementById('loading').style.display =
bool ? 'block' : 'none';
}
});
calendar.render();
});
</script>
Problem solved, thanks to #Patrick Evans for the suggestion, I was adding the get call to the middle of my code, where I had to add it at the end, after the ";" to end the line. I can now reference "rawdata" variable within EventDrop.
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var today = moment().day();
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
defaultDate: today,
editable: true,
eventDrop: function(info) {
editable = rawdata.find(x => x.id === info.event.id).editable;
start= info.event.start.toISOString();
start = moment(info.event.start).format('Y-MM-DD HH:mm:ss');
end= info.event.end.toISOString();
end = moment(info.event.end).format('Y-MM-DD HH:mm:ss');
title = info.event.title;
id = info.event.id;
if (!confirm("Confirm you want to change " + info.event.title + " to " + info.event.start)) {
info.revert();
}
else{
if(editable === 'Y'){
$.ajax({
url: 'php/calendarupdate.php',
data: 'title=' + info.event.title + '&start='+ start +'&end=' + end + '&id=' + info.event.id ,
type: "POST"
});
}
else{
alert("Can only modify this calendar event if you created it. Please ask the event creator to modify.");
calendar.refetchEvents();
}
}
},
navLinks: true, // can click day/week names to navigate views
dayMaxEvents: true, // allow "more" link when too many events
events: {
url: '/php/get-events.php',
failure: function() {
document.getElementById('script-warning').style.display = 'block'
}
},
loading: function(bool) {
document.getElementById('loading').style.display =
bool ? 'block' : 'none';
}
});
$.get( "php/get-events.php", function( data ) {
// data is your result
// Find the value for editable where the event id = the event you are trying to move
rawdata = JSON.parse(data);
});
calendar.render();
});
</script>
I have a MySQL table holding some events to be rendered and a couple PHP pages configured to return those events as JSON objects based on the dates passed to it. When you click or drag an event or calendar date, I have a bootstrap modal that pops up, pre-populated with the information stored in the event (if it was an event you clicked or dragged, otherwise it's just a blank form waiting to add a new event) and when I submit the form, it runs an AJAX query to add/update/delete the event in the MySQL table. Once the AJAX returns successfully, I either call 'removeEvent' and pass it the event id (in case of a delete), call a 'renderEvent' and pass it the object that was used to submit the AJAX query (in case of an add), or both (in case of an update).
For whatever reason, the event never renders correctly using this method. The removeEvent works, and grabs the right event, but the add and update don't render the new event with dates/times. I've tried formatting the start and end in a bunch of different ways, but the event is still rendered incorrectly. Basically, the problem with the rendered event is that it renders it on the correct day, and includes the extra data that I've added, which can be verified by clicking the event and opening the modal, but the start time defaults to midnight of that day, and the end time either doesn't exist, or defaults to midnight of the next day. When I reload the page and it gets the data from PHP, the event is rendered with the correct datetime values.
I've tried logging the event object to the console before rendering it, and I can't find anything that looks out of place, i.e. the output of the event in the console looks the same as the output of one of the JSON objects that are coming out of my PHP page.
Can anybody shine any light on this?
FullCalendar v3.0.1
Scheduler v1.4.0
JQuery v3.1.1
Bootstrap v3.3.7
bootstrap-datetimejs v4.17.43 (https://github.com/Eonasdan/bootstrap-datetimepicker)
The code that is actually rendering the event is in the sendrequest() function, but I'm going to include most of my .js page so you can see what I'm trying to do (I've clipped out a few things to shorten it up, but it's mostly all there)
window.onload = initializepage;
//Calendar documentation: http://fullcalendar.io/docs/
function initializepage()
{
//Build The jQuery Calendar
$('#calendar').fullCalendar({
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives'
defaultView: 'month',
editable: true,
// When you click on an event, it will call the manageevent function and pass the event object to it
eventClick: function($event)
{
manageevent($event);
},
// When you drag an event, it will move it back to where you dragged it
// after this method executed, the eventClick method above is executed
eventResize: function($event, $delta, revertfunc)
{
manageevent($event);
revertfunc();
},
eventDrop: function($event, $delta, revertfunc)
{
manageevent($event);
revertfunc();
},
eventSources:
[
{
url: 'opscalendar_ajax.php',
},
{
url: 'oncall_ajax.php',
data: {
groupname: 'Ops'
}
}
],
fixedWeekCount: false,
header:
{
left: 'prev,next today',
center: 'title',
right: 'timelineDay,agendaWeek,month,basicYear',
},
height: 600,
resourceGroupField: 'Shifts',
resourceGroupText: 'Shifts',
resources:
[
<!-- deleted for brevity -->
],
selectable: true,
selectHelper: true,
// When you click on a date, or drag across dates, call the addevent function
select: function($start, $end)
{
addevent($start, $end);
$('#calendar').fullCalendar('unselect');
},
views: {
<!-- deleted for brevity -->
},
});
// End of JQuery Calendar
//Some jQuery to make it so that the date picked for end time cannot be before the
//date picked for the start time
$(function () {
$('#starttimepicker').datetimepicker();
$('#endtimepicker').datetimepicker({
useCurrent: false //Important! See issue #1075
});
$("#starttimepicker").on("dp.change", function (e) {
$('#endtimepicker').data("DateTimePicker").minDate(e.date);
});
});
// Now we assign some buttons to execute functions instead of submitting a form
document.getElementById('addEventBtn').onclick = executemanageevent;
document.getElementById('updateEventBtn').onclick = executemanageevent;
document.getElementById('deleteEventBtn').onclick = executemanageevent;
// Some JQuery to clear out and fields that are populated in the modal.
$("#manageevent").on('hidden.bs.modal', function()
{
// Reset form values
document.getElementById('hiddenid').value = '';
document.getElementById('shiftdropdown').value = '';
document.getElementById('starttime').value = '';
document.getElementById('endtime').value = '';
document.getElementById('name').value = '';
document.getElementById('alldayradio2').checked = 'checked';
document.getElementById('manageeventalert').innerHTML = '';
});
} // End initializepage function
/* function addevent($start, $end)
*
* Populates modal with the dates from user click or drag
* Enables the add and cancel buttons
* Opens the modal so user can see it
*/
function addevent($start, $end)
{
// Populate dates
$('#starttimepicker').data("DateTimePicker").date($start);
$('#endtimepicker').data("DateTimePicker").minDate($start);
$('#endtimepicker').data("DateTimePicker").date($end);
document.getElementById('alldayradio2').checked = 'checked';
// Show Buttons
$('#addEventBtn').prop("disabled", false);
$('#cancel').prop("disabled", false);
// Show Modal
$('#manageevent').modal({backdrop: 'static'});
return false;
}
/* function closemodal()
*
* Called after a successful request - just closes the modal
*/
function closemodal()
{
$('#manageevent').modal('hide')
}
/* function executemanageevent()
*
* When you click any of the buttons (except cancel) this is executed
* First: it creates an object (like an array, just different)
* Second: disable all the buttons so people can't keep clicking
* Third: take all the values from the modal and put them into the object
* Fourth: put an alert in the modal header (there's a div for it) and let them know we're trying their request
* Fifth: send the object to the sendRequest function
*/
function executemanageevent()
{
// First
var $datatopass = {};
$datatopass.mode = this.getAttribute('mode');
// Second
$('#addEventBtn').prop("disabled", true);
$('#updateEventBtn').prop("disabled", true);
$('#deleteEventBtn').prop("disabled", true);
$('#cancel').prop("disabled", true);
// Third
$titleindex = document.getElementById('name').selectedIndex;
$datatopass.title = document.getElementById('name').options[$titleindex].text;
$datatopass.login = document.getElementById('name').value;
$datatopass.start = document.getElementById('starttime').value;
$datatopass.end = document.getElementById('endtime').value;
$datatopass.resourceId = document.getElementById('shiftdropdown').value;
$datatopass.id = document.getElementById('hiddenid').value;
var $allday = document.getElementsByName('alldayradio');
for($i = 0; $i < $allday.length; $i++)
{
if($allday[$i].checked == true)
{
$datatopass.allDay = $allday[$i].value;
}
}
// Fourth
var $infoalert = "<div class='alert alert-info'><strong>Info: </strong>Attempting to submit your request</div>";
document.getElementById('manageeventalert').innerHTML = $infoalert;
// Fifth
$theresults = sendrequest($datatopass);
console.log($datatopass);
return false;
}
/* function manageevent($event)
*
* Manage event is called when you click on an event, or drag an event
* We assume you're going to update, delete, or copy an event and enable all buttons
* once we've set everything up, show the modal.
*/
function manageevent($event)
{
// Get data from event
$title = $event.title;
$login = $event.login;
$start = $event.start;
$end = $event.end;
$allday = $event.allDay;
$resourceId = $event.resourceId;
$id = $event.id;
// Populate modal fields
document.getElementById('hiddenid').value = $id;
document.getElementById('shiftdropdown').value = $resourceId;
$('#starttimepicker').data("DateTimePicker").date($start);
$('#endtimepicker').data("DateTimePicker").minDate($start);
$('#endtimepicker').data("DateTimePicker").date($end);
document.getElementById('name').value = $login;
if($allday == true)
{
document.getElementById('alldayradio1').checked = 'checked';
}
else
{
document.getElementById('alldayradio2').checked = 'checked';
}
// Enable all buttons
$('#addEventBtn').prop("disabled", false);
$('#updateEventBtn').prop("disabled", false);
$('#deleteEventBtn').prop("disabled", false);
$('#cancel').prop("disabled", false);
// Show the Modal
$('#manageevent').modal({backdrop: 'static'});
return false;
}
/* function sendrequest($thedata)
*
*/
function sendrequest($thedata)
{
var $formdata = "JSON=" + JSON.stringify($thedata);
var $xhttp;
$xhttp = new XMLHttpRequest();
$xhttp.onreadystatechange = function()
{
if($xhttp.readyState == 4 && $xhttp.status == 200)
{
$theresults = JSON.parse($xhttp.responseText);
if($theresults.status == 'failure')
{
var $warnalert = '<div id="warningAlert" class="alert alert-danger"><strong>' +
$theresults.status + '</strong> ' + $theresults.message + '</div>';
document.getElementById('manageeventalert').innerHTML = $warnalert;
if($thedata.mode == 'add')
{
$('#addEventBtn').prop("disabled", false);
$('#cancel').prop("disabled", false);
}
else if($thedata.mode == 'update')
{
$('#addEventBtn').prop("disabled", false);
$('#updateEventBtn').prop("disabled", false);
$('#cancel').prop("disabled", false);
}
else if($thedata.mode == 'delete')
{
$('#deleteEventBtn').prop("disabled", false);
$('#cancel').prop("disabled", false);
}
var $followup = document.createElement('DIV');
$followup.setAttribute('class','alert alert-info');
var $followuptext = document.createTextNode('You may retry your request');
$followup.appendChild($followuptext);
document.getElementById('manageeventalert').appendChild($followup);
}
else if($theresults.status == 'success')
{
var $okayalert = '<div id="warningalert" class="alert alert-success"><strong>' +
$theresults.status + '</strong> ' + $theresults.message + '</div>';
document.getElementById('manageeventalert').innerHTML = $okayalert;
$thedata.start = moment($thedata.start, 'MM/DD/YYYY hh:mm a');
$thedata.end = moment($thedata.end, 'MM/DD/YYYY hh:mm a');
if($thedata.mode == 'add')
{
$thedata.id = $theresults.dbkey;
console.log($thedata);
$('#calendar').fullCalendar('renderEvent', $thedata);
}
else if($thedata.mode == 'update')
{
$('#calendar').fullCalendar('removeEvents', $thedata.id);
console.log($thedata);
$('#calendar').fullCalendar('renderEvent', $thedata);
}
else if($thedata.mode == 'delete')
{
$('#calendar').fullCalendar('removeEvents', $thedata.id);
}
setTimeout(closemodal, 1500);
}
}
};
$xhttp.open("POST", "opscalendar_post.php", true);
$xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
$xhttp.send($formdata);
return false;
}
I am developing a project with AngularJS and using Angular-UI UI-Calendar. In my code I initialize eventSources model for ui-calendar to empty array ([]) and set ui-config "events parameter" to a custom function. That function makes an $http request and then calls the callback function given to the events function.
However, I found out that when I load the page or change the month viewed by left or right buttons, events function called twice. How can I solve that?
Here is my code:
function CalendarCtrl($scope, Data){
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
// Stores all events
var events = [];
/* config object */
$scope.uiConfig = {
calendar:{
height: 450,
editable: true,
header: {
left: 'prev,next',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
buttonText: {
month: "Ay",
week: "Hafta",
day: "Gün",
list: "Ajanda"
},
allDayText: "Tüm gün",
eventLimitText: "daha fazla",
firstDay: 1,
timeFormat: 'H:mm',
axisFormat: 'H:mm',
lazyFetching: true,
// Here listen for calendar change events
events: getEvents
}
};
// For angular ui-calendar element
$scope.eventSources = [];
// Calendar event handlers
function getEvents(from, to, callback){
console.log(from); // For test purposes
// Request for data from server and when it comes, call callback to update calendar
Data.calendar.get(moment(from).unix(), moment(to).unix()).then(function(events){
angular.forEach(events, function(event){
event.start = moment.unix(event.start);
if(event.end){
event.end = moment.unix(event.end);
}
else{
delete event.end;
}
var d = event.start;
if(d.hour() == 0 && d.minute() == 0 && d.second() == 0){
event.allDay = true;
}
if(event.important){
event.className = "important-event";
}
event.editable = true;
});
callback(events);
});
}
I have the solution.
Instead of registering an event handler to $scope.uiConfig.calendar.events, register that same function to $scope.eventSources array. Like that:
$scope.eventSources = [getEvents];
Whenever view changes and calendar needs data it will look at the $scope.eventSources elements. And if an element is a function it will be called and results will be shown in calendar.
We ran into a similar problem in a project and our solution was also in the eventSource initialization putting an empty object inside the array.
$scope.eventSources = [{}];
I'm still struggling to get a calendar to re-render when data changes using meteor blaze. I have put in place an observerChanges function that is firing happily when added, removed or changed are triggered, but I have NO idea how to actually make the calendar update its state.
The handler code is
Meteor.subscribe("reqEvents");
allReqsCursor = Requests.find();
var handle = allReqsCursor.observeChanges({
added: function (id, user) {
console.log("Request added");
},
removed: function () {
console.log("Request removed");
},
changed: function() {
console.log("Request changed");
// $('#calendar').fullCalendar().today();
}
});
And the render function itself is
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',
});
};
How do I hook these together? I've tried a few things (as per the commented out code) but it either blows up or renders the calendar twice.
Is this even the best way? Should I put a deps.autorun in somewhere else?? If so where?
FullCalendar should be instantiated only once in Template.packLayout.rendered function.
I recommend to get reference of fullCalendar instance :
var calendar = null
Template.packLayout.rendered = function(){
// only once !
calendar = $('#calendar').fullCalendar({...});
}
Template.packLayout.helpers ({
data:function(){
allReqsCursor = Requests.find();
var handle = allReqsCursor.observeChanges({
added: function (id, user) {
console.log("Request added");
},
removed: function () {
console.log("Request removed");
},
changed: function() {
console.log("Request changed");
if(calendar){
calendar.today();
}
}
});
return allReqsCursor;
}
})
Template.packLayout.helpers.data is being rerun every time Requests collection is updated.
Something like above code should help you.
Instead using Template.packLayout.helpers.data function you can use:
Deps.autorun(function(){
allReqsCursor = Requests.find();
// update calendar
})
Use the internal calendar functions to re-render the calendar when things change:
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 does the rest for you. Dunno how efficient this is but it works pretty nicely for me.
Now you can just manipulate the subscription 'Calendar' "insert, del etc' and the calendar will work properly.