i'm trying to upgrade my fullCalendar version to the latest ( 3.9.0 ) but i can't seams to make the renderEvent function work. The event simply does not render. I'm also using the latest version of the scheduler plugin ( 1.9.3 )
I tried adding events using the $('#calendar').fullCalendar('renderEvent', event, true) like I used to, but now it does not seams to work.
I also tried $('#calendar').fullCalendar('addEventSource', event) followed by $('#calendar').fullCalendar('refetchEventSources') nothing seams to be working.
Here is my code.
$(document).ready(function() {
//Calendar option
const LOCALE_DEFAULT = 'fr';
const TIMEZONE_DEFAULT = 'local';
const IGNORE_TIMEZONE_DEFAULT = false;
const HEIGHT_DEFAULT = 'auto';
const DROPPABLE_DEFAULT = true;
const ALL_DAY_DEFAULT_DEFAULT = false;
const ALL_DAY_DEFAULT = false;
const ALL_DAY_SLOT_DEFAULT = false;
const TIME_EVENT_DURATION_DEFAULT = '03:00:00';
const SELECTABLE_DEFAULT = true;
const SLOT_EVENT_OVERLAPP_DEFAULT = false;
const SELECT_HELPER_DEFAULT = false;
const EVENT_RESOURCE_EDITABLE_DEFAULT = false;
const PUBLISHED = true;
const SCHEDULER_LICENCE = 'CC-Attribution-NonCommercial-NoDerivatives';
let events = [{"id":2,"title":"test","start":"2018-03-18T15:30:00.000Z","end":"2018-03-18T19:30:00-04:00","creationDate":"2018-03-18 14:55:25","resourceFullName":"testRessource","resourceId":3,"type":"shift"}];
let resources = [{
fullname: "resource 1",
id: 1
},
{
fullname: "resource 3",
id:3
}]
$("#calendar").fullCalendar({
locale: LOCALE_DEFAULT,
timezone: TIMEZONE_DEFAULT,
ignoreTimezone: IGNORE_TIMEZONE_DEFAULT,
slotDuration: '00:30:00',
height: HEIGHT_DEFAULT,
header: {
left: 'prev,next today',
center: 'title',
right: 'timelineDay, weekCustom' + /*, timelineWeek */', month, agendaDay'
},
buttonText: {
today: "today",
timelineDay: "timelineDay",
timelineWeek: "timelineWeek",
month: "month",
agendaDay: "agenda"
},
views: {
weekCustom: {
type: 'timeline',
timeFormat: 'H(:mm)',
buttonText: 'Semaine',
displayEventEnd: true,
duration: {week: 1},
slotDuration: {days: 1}
}
},
defaultView: "weekCustom",
lang: 'fr'/*$filter('translate')('language')*/,
scrollTime: "08:00:00",
resourceAreaWidth: "220px",
events: events,
editable: true,
droppable: DROPPABLE_DEFAULT,
allDayDefault: ALL_DAY_DEFAULT_DEFAULT,
allDay: ALL_DAY_DEFAULT,
allDaySlot: ALL_DAY_SLOT_DEFAULT,
defaultTimedEventDuration: TIME_EVENT_DURATION_DEFAULT,
resourceLabelText: "resources",
schedulerLicenseKey: SCHEDULER_LICENCE,
selectable: SELECTABLE_DEFAULT,
slotEventOverlap: SLOT_EVENT_OVERLAPP_DEFAULT,
selectHelper: SELECT_HELPER_DEFAULT,
eventResourceEditable: EVENT_RESOURCE_EDITABLE_DEFAULT,
resources: resources,
select: function (start, end, jsEvent, view, resourceObj) {
let event = {
start: start,
end: end,
title: "test"
};
//$("#calendar").fullCalendar('addEventSource', [event]);
//$("#calendar").fullCalendar('refetchEventSources', [event]);
//true for stick events
$("#calendar").fullCalendar('renderEvent', event, true);
},
eventClick: function (event, jsEvent, view) {
},
eventDrop: function (event, delta, revertFunc) {
},
eventResize: function (event, dayDelta, minuteDelta, revertFunc, jsEvent, ui, view) {
},
viewRender: function (view) {
},
loading: function (bool, view) {
}
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar-scheduler/1.9.3/scheduler.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.21.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar-scheduler/1.9.3/scheduler.min.js"></script>
<div id="calendar">
</div>
P.S. use the timeline day for a more efficient test.
Your code works fine, and creates the event quite happily - try it: select a time period (in any view), remember the date/time you chose, and then go to your "month" view. You will see the created event in the timeslot you selected.
The problem comes when you try to view the event in a view which uses resources. Your code does not specify a resourceId for the new event. Therefore, fullCalendar has no idea which resource to show the event on, and so cannot display it at all in any resource-aware view.
To fix this, simply take the resourceId supplied in the resourceObj parameter of the select callback, and include it in your new event object:
let event = {
start: start,
end: end,
title: "test",
resourceId: resourceObj.id
};
P.S. you should also run "unselect" after the call to "renderEvent", otherwise the timeslot chosen will remain highlighted on the calendar behind the created event (until or unless the user clicks elsewhere). In some views this is more obvious than others, but it doesn't look right. The command is simply:
$("#calendar").fullCalendar('unselect');
Related
Does anybody know why is the end date null on those "allday=false" events?
Fiddle Sample: https://jsfiddle.net/L1g0z3jd/
I instantiate it differently from the start date, it shows just fine in the calendar view, but for some reason I can't understand whenever i get clientEvents, even thought i have not changed it, I got a null in the event end date!
PS: Just for the sake of "conscience" I must add ... I'm using and old version of google chrome (v 57.0.2987.133 64-bit) and an old ubuntu version (Linux Mint 18.1 Serena)
Its getting me crazy! Thanks!
HTML Code:
<button onclick="javascript:getEvents()">Get Events</button>
<div id='calendar'></div>
Javascript Code:
$(function() {
$('#calendar').fullCalendar({
header: false,
allDaySlot: false,
visibleRange: {start: moment('2000-01-02'), end: moment('2000-01-09')},
editable: true,
selectable: true,
views: {
settimana: {
type: 'agenda',
columnFormat: 'ddd',
hiddenDays: []
}
},
defaultView: 'settimana',
defaultDate: $.fullCalendar.moment().startOf('week'),
slotMinutes: 30,
events: [
$.fn.getAgendaWorktime(1, "08:00:00", 60),
$.fn.getAgendaWorktime(2, "08:30:00", 120),
],
select: function(startDate, endDate) {
$('#calendar').fullCalendar('renderEvent', {
title: 'free time',
start: startDate.format(),
end: endDate.format(),
allDay: false
});
},
eventClick: function(calEvent, jsEvent, view) {
console.log(calEvent, jsEvent, view);
if(doubleClick==calEvent._id){
if (confirm('Delete it?')) {
$('#calendar').fullCalendar('removeEvents',calEvent._id);
}
doubleClick = null;
}else{
doubleClick=calEvent._id;
}
},
});
});
function getEvents() {
var e=0,err=false,$data = []
$('#calendar').fullCalendar('clientEvents').forEach(periodo => {
if (periodo.end==null || periodo.start.format().substr(0,10)!=periodo.end.format().substr(0,10)) {
if (e==0) {
err = true;
e++;
alert('Event startint at '+periodo.start.format()+' cant spread to multiple days');
}
} else {
$data.push({'ini': periodo.start.format(), 'fim': periodo.end.format()});
}
});
alert($data);
}
jQuery.fn.getAgendaWorktime = function ($dow, $start, $elapsed) {
var r = {
allDay: false,
title: 'free time',
start: new Date('2000-01-02 '+$start),
end: new Date('2000-01-02 '+$start)
};
r.start.setDate(r.start.getDate()+$dow);
r.end.setDate(r.end.getDate()+$dow);
r.end.setHours(r.end.setHours()+($elapsed*60));
return(r);
}
I figured out how to solve the question, I will reply to it here for I have not found any workaround or further analysis of the problem in the internet ....
I didn't review my problem to determine if it was specific related to the fact that I was setting the event's end time incorrectly and the calendar wasn't giving me any errors on the issue or anything else, but if you're gowing by the same road i went i can tell you:
Check to see if the end time is been created corretly (that seams to be my real mistaken, I was using setHours instead getHours in the getAgendaWorktime function, which turned the final value to be null. I corrected it in the sample below, but let it incorrectly in the fiddle to show the use of the forceEventDuration attribute);
Set "forceEventDuration" parameter to "true" (that forces the "end" attribute to always be filled easying me up in my code for I can always awaits for an string from ".format()" method of the attibute);
for meny reasons fullcalendar.io some times does not sets the event end date and this was getting me problems whenever avaluating the event end time (Ok, I could work around it but I was intrigged for why does it was getting me those results when it sould not, and the answare was a buged code). With "forceEventDuration: true" fullcalendar gave me the end time every time therefor i could find out that the input method i was using was seting the end date incorrectly and gave me the chance to correct it as well.
Links related:
Calendar parameter documentation https://fullcalendar.io/docs/forceEventDuration
Corrected Fiddle https://jsfiddle.net/gjrfox05/
I hope this answer could be of some help for newcomers at fullcalendar.io as me.
Fiddle Javascript part corrected sample:
$(function() {
$('#calendar').fullCalendar({
header: false,
allDaySlot: false,
forceEventDuration: true,
visibleRange: {start: moment('2000-01-02'), end: moment('2000-01-09')},
editable: true,
selectable: true,
views: {
settimana: {
type: 'agenda',
columnFormat: 'ddd',
hiddenDays: []
}
},
defaultView: 'settimana',
defaultDate: $.fullCalendar.moment().startOf('week'),
slotMinutes: 30,
events: [
$.fn.getAgendaWorktime(1, "08:00:00", 60),
$.fn.getAgendaWorktime(2, "08:30:00", 120),
],
select: function(startDate, endDate) {
$('#calendar').fullCalendar('renderEvent', {
title: 'free time',
start: startDate.format(),
end: endDate.format(),
allDay: false
});
},
eventClick: function(calEvent, jsEvent, view) {
console.log(calEvent, jsEvent, view);
if(doubleClick==calEvent._id){
if (confirm('Delete it?')) {
$('#calendar').fullCalendar('removeEvents',calEvent._id);
}
doubleClick = null;
}else{
doubleClick=calEvent._id;
}
},
});
});
function getEvents() {
var e=0,err=false,$data = []
$('#calendar').fullCalendar('clientEvents').forEach(periodo => {
if (periodo.end==null || periodo.start.format().substr(0,10)!=periodo.end.format().substr(0,10)) {
if (e==0) {
err = true;
e++;
alert('Event startint at '+periodo.start.format()+' cant spread to multiple days');
}
} else {
$data.push({'ini': periodo.start.format(), 'fim': periodo.end.format()});
}
});
alert($data[0].fim);
}
jQuery.fn.getAgendaWorktime = function ($dow, $start, $elapsed) {
var r = {
allDay: false,
title: 'free time',
start: new Date('2000-01-02 '+$start),
end: new Date('2000-01-02 '+$start)
};
r.start.setDate(r.start.getDate()+$dow);
r.end.setDate(r.end.getDate()+$dow);
r.end.setHours(r.end.getHours()+($elapsed*60));
return(r);
}
By default FullCalendar end date null when event end_date = start_date.
I Just pass another fiend with same date from database (Django View).
event_sub_arr['end'] = end_date
event_sub_arr['end_same_date'] = end_date
And check in javaScript
eventClick: function(info) {
var modal = document.getElementById('DeleteEventModal')
getEventDeleteUrl(info.event.id)
getEventUpdateUrl(info.event.id)
modal.style.display = 'block'
calendar.unselect()
var start = info.event.start
var end_same_date = info.event.end_same_date
var end = info.event.end || end_same_date
$("#event_id_name").text(info.event.title)
$("#event_id_start").text(moment(start).format('h:mm:ss a, MMMM Do YYYY'))
$("#event_id_end").text(moment(end).format('h:mm:ss a, MMMM Do YYYY'))
console.log(info.event.start)
console.log(info.event.end)
console.log({{ event_data|safe }})
},
ITS WORK FOR ME
I am working on a react project using npm fullcalendar. there is a requirement that I need to change the color of the current day. I managed to do that using the following :
$('.fc-today').attr('style','background-color:#40cc25');
however, the problem is that when I click on next month or previous month it change the color to the original color of the library. how can I keep my new background color?
here is my code :
var EventCalendar = React.createClass({
mixins: [History],
getInitialState: function () {
return {
isModalOpen: false
};
},
_onCalendarSelect: function (start, end, jsEvent, view) {
if (!AuthStore.isAdministrator())
return;
var event = {
start: start,
end: end
};
this.setState({
event: event,
isUpdate: false
});
this.props.onNewEvent(event);
},
_onEventSelect: function (event) {
this.props.onEventSelect(event)
},
_loadEvents: function(start, end, timezone, callback) {
var events = EventStore.getInRange(start, end, this.props.environmentId);
if (!EventStore.isLoaded(start.format("YYYY-MM"))) {
EventActions.fetchData(start, end, this.props.environmentId)
} else {
callback(events);
}
},
_onEventStoreUpdate: function() {
// This is fix for IE11 required by bug RTC #458121
var moment = this.$fullCalendarContainer.fullCalendar('getDate');
this.$fullCalendarContainer.fullCalendar('destroy');
this.$fullCalendarContainer.fullCalendar({
defaultView: 'month',
defaultDate : moment,
selectable: true,
eventLimit: true,
eventClick: this._onEventSelect,
select: this._onCalendarSelect,
events: this._loadEvents,
displayEventEnd: false,
displayEventTitle: true,
nextDayThreshold: false
});
$('.fc-today').attr('style','background-color:#40cc25');
// For other browsers we can just use : this.$fullCalendarContainer.fullCalendar('refetchEvents');
},
componentWillMount: function () {
EventActions.invalidateData();
},
componentDidMount: function () {
this.$fullCalendarContainer = $(this.getDOMNode());
this.$fullCalendarContainer.fullCalendar({
defaultView: 'month',
selectable: true,
eventLimit: true,
eventClick: this._onEventSelect,
select: this._onCalendarSelect,
events: this._loadEvents,
displayEventEnd: false,
displayEventTitle: true,
nextDayThreshold: false
});
EventStore.addChangeListener(this._onEventStoreUpdate);
},
componentWillUnmount: function () {
this.$fullCalendarContainer.fullCalendar('destroy');
EventStore.removeChangeListener(this._onEventStoreUpdate);
EventActions.invalidateData();
},
render: function () {
return <div/>
}
});
module.exports = EventCalendar;
and this how I am calling the componenet:
<EventCalendar onEventSelect={this._onEventSelect} onNewEvent={this._onNewEvent} environmentId={this.props.params.id}/>
Try using the eventAfterAllRender callback. When events are done rendering then it will style the element. The only downside is there may be a slight delay before it is styled but it seems to be just a few milliseconds. Here is a JSFiddle.
eventAfterAllRender: function(view) {
$('.fc-today').attr('style','background-color:#40cc25');
}
In my fullcalendar http://fullcalendar.io/
I want to prevent a user to be able to create an event on multiple days
$('#calendar').fullCalendar({
defaultView: 'agendaWeek',
lang: "fr",
header: false,
timezone: 'local',
minTime: "08:00:00",
columnFormat: 'dddd',
selectHelper: true,
selectable: true,
select: function(start, end, id, allDay) {
var eventData = {
start: start,
end: end,
id: 1,
block: true,
editable: true,
backgroundColor: "#469278"
};
// console.log(moment(eventData.start["_d"]).format("dddd"));
// console.log(moment(eventData.end["_d"]).format("dddd"));
$('#calendar').fullCalendar('renderEvent', eventData, true); // stick? = true
// console.log(eventData);
if (moment(eventData.start["_d"]).format("dddd") != moment(eventData.end["_d"]).format("dddd")) {
$('#calendar').fullCalendar('unselect');
};
var day = moment(eventData.start["_d"]).format("dddd");
var start_time = moment(eventData.start["_d"]).format("HH:mm");
var end_time = moment(eventData.end["_d"]).format("HH:mm");
var id = moment(eventData.end["_id"]);
var slot = {
day: day,
start_time: start_time,
end_time: end_time
};
array_dispo.push(slot);
$("#dispo_array").val(JSON.stringify(array_dispo));
$('#calendar').fullCalendar('unselect');
},
});
});
When a user is selecting a start date that is different from the end date of his event I thus tried to use the unselect method from the doc http://fullcalendar.io/docs/selection/unselect_method/ like this :
if (moment(eventData.start["_d"]).format("dddd") != moment(eventData.end["_d"]).format("dddd")) {
$('#calendar').fullCalendar('unselect');
};
But unfortunately this code doesnt automatically deselects the current selection...
You can do a check in your select method and then decide whether you want to render the event or not.
I also use Moment.js to calculate dates and durations, this library is included with FullCalendar (http://fullcalendar.io/docs/utilities/Moment/)
So I played around and came up with this:
select: function (start, end) {
var mEnd = $.fullCalendar.moment(end);
var mStart = $.fullCalendar.moment(start);
if (mEnd.isAfter(mStart, 'day')) {
$('#calendar').fullCalendar('unselect');
} else {
$('#calendar').fullCalendar('renderEvent', {
start: mStart,
end: mEnd,
allDay: false
},
true // stick the event
);
$('#calendar').fullCalendar('unselect');
}
}
Here is the jsfiddle if you want to see it in action: here
You can do it using this way:
eventResize: function(eventResizeInfo) {
console.log('eventResize is called');
var event = eventResizeInfo.event;
if (event.start.getDay() !== event.end.getDay()) {
eventResizeInfo.revert();
}
},
To prevent users from selecting multiple days at a time
selectAllow: function(selectedEvent) {
let startDate = selectedEvent.start;
let endDate = selectedEvent.end;
endDate.setSeconds(endDate.getSeconds() - 1);
if (startDate.getDate() === endDate.getDate()) {
return true;
} else {
return false;
}
}
Simply add the following option to your calendar:
selectAllow: (selectInfo) => { return selectInfo.start.getDay() === selectInfo.end.getDay() },
I've just started out using this plugin and I am having some trouble removing events that I have just created. I can delete all the events when using eventClick, but not particular ones on eventClick.
Any help would be appreciated. Here is my code.
<script type='text/javascript'>
$(document).ready(function() {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
var calendar = $('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
selectable: true,
selectHelper: true,
select: function(start, end, allDay) {
var title = prompt('Trade Show Name:');
if (title) {
calendar.fullCalendar('renderEvent',
{
title: title,
start: start,
end: end,
allDay: allDay,
id: 12
},
true // make the event "stick"
);
$('input[name="startDate"]').val(start);
}
calendar.fullCalendar('unselect');
},
eventClick: function(calEvent, jsEvent, view) {
$('#calendar').fullCalendar('removeEvents', function (calEvent) {
return true;
});,
editable: true
});
});
You can do this in 2 ways:
1) Set a unique ID to each of your events and pass those IDs to the removeEvents call.
eventClick: function (calEvent, jsEvent, view) {
$('#calendar').fullCalendar('removeEvents', calEvent._id);
}
Here _id is the unique ID fullCalendar generates.
2) Pass a filter function to delete the event you want.
Considering that you are trying to do this in eventClick, I would suggest you use the 2nd. An example to your case is as follows:
eventClick: function (calEvent, jsEvent, view) {
$('#calendar').fullCalendar('removeEvents', function (calEvent) {
return true;
});
}
Here the filter function passed to removeEvents accepts the event you want to delete and returns true. Since you are doing this in eventClick, all you have to do is pass calEvent.
Hope this helps!
I'm trying to load data into an FullCalendar, using Json. But i can't load the data:
The controller:
ppublic ActionResult GetEvents()
{
List<Models.Events> events = new List<Models.Events>()
{
new Models.Events("Fremvising","2013-01-11T14:08:00Z", "2013-01-11T16:09:00Z", false),
new Models.Events("Fremvising","2013-01-12T15:09:00Z", "2013-01-11T17:10:00Z", false),
new Models.Events("Fremvising","2013-01-13T16:10:00Z", "2013-01-11T18:11:00Z", false),
new Models.Events("Fremvising","2013-01-14T17:11:00Z", "2013-01-11T19:12:00Z", false),
new Models.Events("Fremvising","2013-01-15T18:12:00Z", "2013-01-11T20:13:00Z", false),
new Models.Events("Fremvising","2013-01-16T19:13:00Z", "2013-01-11T21:14:00Z", false)
};
return Json(events, JsonRequestBehavior.AllowGet);
}
And the javascript:
$(document).ready(function () {
/* initialize the external events
-----------------------------------------------------------------*/
$('#external-events div.external-event').each(function () {
// create an Event Object (http://arshaw.com/fullcalendar/docs/event_data/Event_Object/)
// it doesn't need to have a start or end
var eventObject = {
title: $.trim($(this).text()) // use the element's text as the event title
};
// store the Event Object in the DOM element so we can get to it later
$(this).data('eventObject', eventObject);
// 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
});
});
/* initialize the calendar
-----------------------------------------------------------------*/
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'agendaWeek,agendaDay',
height: 650,
// url:,
}, events: [
$.getJSON("#Url.Action("GetEvents")", function (locationsArray) {
$.each(locationsArray, function (index, location) {
title : location.title;
start: location.start;
end: location.end;
allDay: location.editable; // will make the time show
});
})
],
allDaySlot: false,
//minTime: 10,
//maxTime: 21,
dayNames: ['Søndag', 'Mandag', 'Tirsdag', 'Onsdag',
'Torsdag', 'Fredag', 'Lørdag'],
dayNamesShort: ['Søn', 'Man', 'Tirs', 'Ons', 'Tors', 'Fre', 'Lør'],
editable: true,
defaultView: 'agendaWeek',
droppable: true, // this allows things to be dropped onto the calendar !!!
drop: function (date, allDay) { // this function is called when something is dropped
// retrieve the dropped element's stored Event Object
var originalEventObject = $(this).data('eventObject');
// we need to copy it, so that multiple events don't have a reference to the same object
var copiedEventObject = $.extend({}, originalEventObject);
// assign it the date that was reported
copiedEventObject.start = date;
copiedEventObject.allDay = allDay;
// render the event on the calendar
// the last `true` argument determines if the event "sticks" (http://arshaw.com/fullcalendar/docs/event_rendering/renderEvent/)
$('#calendar').fullCalendar('renderEvent', copiedEventObject, true);
// is the "remove after drop" checkbox checked?
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the "Draggable Events" list
$(this).remove();
}
}
});
});
$('#tabs').tabs({
show: function (event, ui) {
$('#calendar').fullCalendar('render');
}
});
For some reason it doesnt get the json result.
The Json request
0: {title:Fremvising, start:2013-01-11T14:08:00Z, end:2013-01-11T16:09:00Z, editable:false}
1: {title:Fremvising, start:2013-01-12T15:09:00Z, end:2013-01-11T17:10:00Z, editable:false}
2: {title:Fremvising, start:2013-01-13T16:10:00Z, end:2013-01-11T18:11:00Z, editable:false}
3: {title:Fremvising, start:2013-01-14T17:11:00Z, end:2013-01-11T19:12:00Z, editable:false}
4: {title:Fremvising, start:2013-01-15T18:12:00Z, end:2013-01-11T20:13:00Z, editable:false}
5: {title:Fremvising, start:2013-01-16T19:13:00Z, end:2013-01-11T21:14:00Z, editable:false}
You have incorrectly defined the events property of your FullCalendar. You have assigned it to a javascript array but that's incorrect because your data is coming from the server. You should set it to an anonymous function. Also you seem to be triggering an AJAX request to the server but inside the success callback you are doing absolutely nothing with the results other than looping through them but you never pass them to the FullCalendar. Here's the correct way to define the events property:
events: function (start, end, callback) {
$.getJSON("#Url.Action("GetEvents")", function (locationsArray) {
var result = $(locationsArray).map(function () {
return {
title: this.title,
start: this.start,
end: this.end,
allDay: this.editable
};
}).toArray();
callback(result);
});
},
Notice how we are performing a transformation over the result coming from the server (which wouldn't have been necessary of course if you had used view models) and then we are calling the callback property with this transformed resultset.
Alright and here's a step by step guide:
Create a new ASP.NET MVC 4 application using the Internet Application Template
Modify HomeController to look like this:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult GetEvents()
{
var events = new[]
{
new { title = "Fremvising", start = "2013-01-11T14:08:00Z", end = "2013-01-11T16:09:00Z", editable = false },
new { title = "Fremvising", start = "2013-01-12T15:09:00Z", end = "2013-01-11T17:10:00Z", editable = false },
new { title = "Fremvising", start = "2013-01-13T16:10:00Z", end = "2013-01-11T18:11:00Z", editable = false },
new { title = "Fremvising", start = "2013-01-14T17:11:00Z", end = "2013-01-11T19:12:00Z", editable = false },
new { title = "Fremvising", start = "2013-01-15T18:12:00Z", end = "2013-01-11T20:13:00Z", editable = false },
new { title = "Fremvising", start = "2013-01-16T19:13:00Z", end = "2013-01-11T21:14:00Z", editable = false }
};
return Json(events, JsonRequestBehavior.AllowGet);
}
}
Download FullCalendar and put it into the Scripts folder
Modify ~/Views/Shared/_Layout.cshtml to look like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title - My ASP.NET MVC Application</title>
#RenderSection("styles", required: false)
</head>
<body>
#RenderBody()
#Scripts.Render("~/bundles/jquery")
#RenderSection("scripts", required: false)
</body>
</html>
And ~/Views/Home/Index.cshtml like that:
<div id="calendar"></div>
#section styles {
<link href="~/scripts/fullcalendar-1.5.4/fullcalendar/fullcalendar.css" rel="stylesheet" />
}
#section scripts {
<script type="text/javascript" src="~/scripts/fullcalendar-1.5.4/fullcalendar/fullcalendar.js"></script>
<script type="text/javascript">
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'agendaWeek,agendaDay',
height: 650,
},
events: function (start, end, callback) {
$.getJSON("#Url.Action("GetEvents")", function (locationsArray) {
var result = $(locationsArray).map(function () {
return {
title: this.title,
start: this.start,
end: this.end,
allDay: this.editable
};
}).toArray();
callback(result);
});
},
allDaySlot: false,
dayNames: ['Søndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag'],
dayNamesShort: ['Søn', 'Man', 'Tirs', 'Ons', 'Tors', 'Fre', 'Lør'],
editable: true,
defaultView: 'agendaWeek',
droppable: true,
drop: function (date, allDay) { // this function is called when something is dropped
// retrieve the dropped element's stored Event Object
var originalEventObject = $(this).data('eventObject');
// we need to copy it, so that multiple events don't have a reference to the same object
var copiedEventObject = $.extend({}, originalEventObject);
// assign it the date that was reported
copiedEventObject.start = date;
copiedEventObject.allDay = allDay;
// render the event on the calendar
// the last `true` argument determines if the event "sticks" (http://arshaw.com/fullcalendar/docs/event_rendering/renderEvent/)
$('#calendar').fullCalendar('renderEvent', copiedEventObject, true);
// is the "remove after drop" checkbox checked?
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the "Draggable Events" list
$(this).remove();
}
}
});
</script>
}