Using FullCalendar v3.9.0 with jQuery v3.3.1. I have a SailsJS application that's getting the calendar data from MySQL.
this.me.calendar from MySQL currently looks like this.
[{"start":"2018-07-04T13:30:00","end":"2018-07-04T18:00:00","works":["2"]}]
And my FullCalendar code looks like this.
let that = this;
that.me.calendar = this.me.calendar;
$('#calendar').fullCalendar({
header: {
left: 'today prev,next',
center: 'title',
right: 'agendaWeek,agendaDay'
},
views: {
week: {
titleFormat: 'DD.MM.YYYY'
}
},
defaultView: 'agendaWeek',
locale: 'fi',
weekends: false,
scrollTime: '07:00',
businessHours: {
start: '7:00',
end: '21:00',
},
events: function(start, end, timezone, callback) {
let events = that.me.calendar ? that.me.calendar : [];
console.log(events);
callback(events);
},
editable: true,
selectable: true,
selectHelper: true,
select: (start, end) => {
let duration = (end - start) / 1000;
if (duration == 1800) {
// Set default duration to 1 hour
end = start.add(30, 'mins');
return $('#calendar').fullCalendar('select', start, end);
}
let eventData = {
start: start,
end: end,
works: []
}
$('#calendar').fullCalendar('renderEvent', eventData);
$('#calendar').fullCalendar('unselect');
},
eventClick: (event, element) => {
$('#event-works').text(event.works.join(','));
$('#start-date').text(moment(event.start).format('d.MM.YYYY HH:mm'));
$('#end-date').text(moment(event.end).format('d.MM.YYYY HH:mm'));
$('#workModal').modal('show');
$('#add-work-to-event').click(() => {
let work = $('#work').val();
if(_.includes(event.works, work)) return;
event.works.push(work);
$('#event-works').text(event.works.join(','));
});
}
});
While the code above doesn't send the GET, it doesn't display the events in the calendar. However, if I change the events to events: this.me.calendar, the SailsJS console displays GET /account/%22[%7B/%22start/%22:/%222018-07-04T13:30:00/%22,/%22end/%22:/%222018-07-04T18:00:00/%22,/%22works/%22:[/%222/%22]%7D]%22 (1ms 404).
I also tried changing it to events: JSON.stringify(this.me.calendar), which still gave the GET request in console.
If I enter the array in the events on it's own, it is working. Also the console.log inside the events function is returning the same array.
Is there a way for me to simply enter my array for FullCalendar, or do I have to make it get the JSON from an URL?
I managed to solve the issue by changing the let events inside of my events function to let events = that.me.calendar ? JSON.parse(that.me.calendar) : []; and now the events are being displayed.
Related
I have been using jQuery along with fullcalendar to create a calendar that displays events from a database using php and MYSQL.
The calendar looks like this.
The events are shown in red. I would like to be able to add a button in each of the cells that do not have an event to allow the user to be able to add one.
Here is the code I have tried
viewRender: function (view) {
$(".fc-content").append('<button>Add</button>')
}
my full code.
$(document).ready(() => {
const calendar = $('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'agendaWeek,agendaDay'
},
defaultView: 'agendaWeek',
defaultTimedEventDuration: '01:00',
allDaySlot: false,
scrollTime: '09:00',
businessHours: {
dow: [ 2, 3, 4, 5, 6 ],
start: '09:00',
end: '17:30'
},
//viewRender: function (view) {
// $(".fc-content").append('<button>Book</button>');
// },
long: /^en-/.test(navigator.language) ? 'en' : 'zh-cn',
eventOverlap: (stillEvent, movingEvent) => {
return true;
},
events:
<?php echo $json;?>
//'2018-12-12T15:00+08:00'
//},
//{
//title: '',
//start: '' //'2018-12-12T12:00+08.00'
,
eventColor: '#FF0000',
edittable: true,
selectable: true,
selectHelper: true,
select: (start, end) => {
const duration = (end - start) / 1000;
if(duration == 1800){
// set default duration to 1 hr.
end = start.add(30, 'mins');
return
calendar.fullCalendar('select', start, end);
}
let eventData;
if (title && title.trim()) {
eventData = {
title: title,
start: start,
end: end
};
calendar.fullCalendar('renderEvent', eventData);
}
calendar.fullCalendar('unselect');
},
eventRender: (event, element) => {
const start = moment(event.start).fromNow();
element.attr('title', start);
},
loading: () => {}
});
});
Ok first off, unless the button is required from UI/UX perspective, you can skip adding the button and just work with fullCalendars built-in method/events.
example (skipping irrelevant options):
fullCalendar({
...
editable: true,
selectable: true, // makes each day selectable
select: function (start, end) {
// in this select callback you are given the start and end dates of the user's selection
// when a user selects any cells this will fire and you can do stuff in here
// fullcalendar will always give 2 dates as callback, even if the user only selected 1
// date, the 'end' will correspond to the next day actually...
events: [{event1},{event2},{event3}], // use this to initialize the events already //existing
eventClick: function (event) {
// this is the handler that will run when the user clicks on an event, not a day! an //event on a day
}
}
})
I hope this helps, you can always read more on the docs
You do not need button ..
you can do it in function eventClick this trigger in click on any day
$('#calendar').fullcalendar({
eventClick : function(xEvent, jsEvent, view){ hus_eventClick(xEvent, jsEvent, view);} ,
});
and in function show dialog box to add event ..
https://fullcalendar.io/docs/dayClick
INTRO
Hey, I'm writing page using jquery fullcalendar to display events from my Salesforce org. I'm struggling to implement conditional rendering of events which happen to be on the exact same time in calendar, what looks like this:
SPECIFICATION
The green on the left represent working hours of dentist and after clicking one of them user is redirected to fill out the form, after that there is created event which is marked as red one.
PROBLEM
I would like to implement function or whatever makes sense to remove, or overlap the events on the left side (green or red). Is there any specific concept I should be using ? Thanks for your time.
Here is a code which I wrote :
function getEventData(dentistId) {
alert(dentistId);
Visualforce.remoting.Manager.invokeAction(
'{!$RemoteAction.CalendarController.eventData}', dentistId,
function(result, event){
if (event.status) {
evt = JSON.parse(result);
console.log(evt);
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay,listDay',
},
eventClick: function (calEvent, jsEvent, view) {
if(calEvent.editable === true) {
var start = moment(calEvent.start).format('YYYY-MM-DD HH:mm:ss');
var end = moment(calEvent.end).format('YYYY-MM-DD HH:mm:ss');
jQuery('[id$=startStringField]').val(start);
jQuery('[id$=endStringField]').val(end);
passToController();
} else {
return false;
}
},
eventOverlap: false,
defaultDate: $('#calendar').fullCalendar('today'),
navLinks: true,
events: evt,
eventRender: function(event, element) {
element.qtip({
content: event.description
});
},
textColor: 'white',
height:650,
})
} else if (event.type === 'exception') {
console.log(event.message);
} else {
console.log(event.message);
}
},
{escape: false}
);
}
The result is a string in json format which represent array of events to be displayed which are then parsed:
Json which is parsed to array of objects
I am trying to build an application that creates events within fullcalendar. I don't allow user to create an "allDay" event at all at the client side but they still can see it within the view. Is there any method to remove allDays from views completely?
function initCalendar {
if (!jQuery().fullCalendar) {
return;
}
var date = new Date(),
started,
ended
var header = {};
var calendar = $('#calendar').fullCalendar({
header: header,
selectable: true,
selectHelper: true,
select: function (start, end, allDay) {
$('#fc_create').click();
var dateStart = start;
var dateEnd = end;
$(".antosubmit").on("click", function() {
var title = $("#reservation-title").val();
if (title) {
var event = {
editable: true,
title: title,
start: dateStart,
end: dateEnd,
allDay: false
}
calendar.fullCalendar('renderEvent', event, true);
calendar.fullCalendar('unselect');
#('.antoclose').click();
return false;
}
else {
////alert here
}
})
}
})
}
From the docs:
allDaySlot: false
https://fullcalendar.io/docs/agenda/allDaySlot/
** Update for v5:
https://fullcalendar.io/docs/allDaySlot
I'm using the jquery fullcalendar plugin. I can display dynamic dates on a button click. The issue I have now is when loading the dates from the db all the dates populate just one day.
Here is the code with the call to the web service:
$('#calendar').fullCalendar({
header: {
left: 'prev, next today',
center: 'title',
right: 'month, agendaWeek, agendaDay'
},
defaultView: 'month',
editable: true,
allDaySlot: false,
selectable: true,
slotMinutes: 15,
events: 'DAL/WebService1.asmx/GetEvents',
allDay:false
});
Here is the date from that web method
$('#calendar').fullcalendar('renderEvent',event_object,'stick')
This will attach your event to its date on the calendar. The event_object only needs a title and a start date to be valid, but I'd suggest adding an id to make editing/deleting easier.
Render event documentation
Figured out how to get the calendar to render dates separately with this code here. Hopefully helps somebody in the future
var events = [];
$('#calendar').fullCalendar({
events: function (start, end, timezone,callback) {
$.ajax({
url: 'DAL/WebService1.asmx/GetEvents',
dataType: 'json',
success: function (data) {
console.log(data);
var events = [];
$(data).each(function (index, d) {
events.push({
title: d.title,
start: d.startDate
});
});
callback(events);
}
});
}
});
I have this code and I'm trying to make sense of it - I'm not really sure how it works-
{% if book %}
<script type='text/javascript'>
$(document).ready(function() {
$.get('/ajax/book/{{ book.id }}/timetable/', {}, function(data) {
data = JSON.parse(data);
var events = new Array();
for (var i in data) {
events.push({
id: data[i].id,
title: '{{ request.user.name }}',
start: Date.parse(data[i].startTime, "yyyy-MM-dd HH:mm:ss"),
end: Date.parse(data[i].endTime, "yyyy-MM-dd HH:mm:ss"),
allDay: false
});
}
var calendar = $('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'agendaDay,agendaWeek'
},
theme: true,
contentHeight: 400,
defaultView: 'agendaWeek',
selectable: true,
selectHelper: true,
eventClick: function(calEvent, jsEvent, view) {
},
select: function(start, end, allDay) {
var title = '{{ request.user.name }}';
$.post('/ajax/book/{{ book.id }}/timetable/new/', {
csrfmiddlewaretoken: getCookie('csrftoken'),
startTime: start.format("yyyy-mm-dd HH:MM:ss"),
endTime: end.format("yyyy-mm-dd HH:MM:ss"),
}, function(data) {
calendar.fullCalendar('renderEvent',
{
title: title,
start: start,
end: end,
allDay: allDay
},
true // make the event "stick"
);
});
calendar.fullCalendar('unselect');
},
editable: true,
events: events,
eventResize: function(event, dayDelta, minuteDelta, revertFunc) {
alert(
"The end date of " + event.title + " has been moved " +
dayDelta + " days and " +
minuteDelta + " minutes."
);
if (!confirm("Is this okay?")) {
revertFunc();
}
}
});
});
});
</script>
From what I can tell, ajax/book/.../timetable and ajax/book/.../timetable/new call book_timetable(request,id) and book_timetable_new(request,id)-
url(r'^ajax/book/(?P<bookid>\d+)/timetable/$', twobooks.ajax.views.book_timetable),
url(r'^ajax/book/(?P<bookid>\d+)/timetable/new/$', twobooks.ajax.views.book_timetable_new),
where the functions are -
def book_timetable(request, bookid):
book = get_object_or_404(Book, id=bookid)
rawslots = TimeSlot.objects.filter(user=request.user).filter(book=book)
slots = []
for rawslot in rawslots:
slot = {
'id': rawslot.id,
'startTime': str(rawslot.startTime),
'endTime': str(rawslot.endTime),
}
slots.append(slot)
return HttpResponse(simplejson.dumps(slots))
def book_timetable_new(request, bookid):
book = get_object_or_404(Book, id=bookid)
startTime = datetime.strptime(request.POST['startTime'], "%Y-%m-%d %H:%M:%S")
endTime = datetime.strptime(request.POST['endTime'], "%Y-%m-%d %H:%M:%S")
timeslot = TimeSlot(
user = request.user,
book = book,
startTime = startTime,
endTime = endTime,
)
timeslot.save()
return JSONify("")
I'm trying to do something similar to this, except with other data, which is why I'm trying to get how this works. If anyone could explain it to me it'd be great!
This is a fairly standard AJAX pattern. The template is rendered by the original view, as normal. In the course of rendering, some elements of the Javascript which are marked as Django template variables are filled in - eg {{ book.id }} and {{ request.user.name }} - so that by the time it gets to the browser, those are indistinguishable from the rest of the JS.
Now, the Javascript makes a call to the server, passing those elements. The server responds with JSON data, which is parsed by the function which is the third parameter to the .get call. I haven't looked too deeply into that function, but it seems to be using that data to instantiate a fullCalendar, which is presumably a separate jQuery script.
One slightly strange thing is that the AJAX call is set to run as soon as the browser has loaded the page - normally there's no point doing that, since you could simply include the data in the original template. Usually AJAX is set to execute in response to some event in the browser, such as a button click.