Update: I provided a best answer to my problem. Feel free to improve the readability and/or efficiency.
Problem: Using fullcalendar.io in my requireJS set up, Event objects (received from an AJAX call to a .ashx handler) are populated on the calendar on every next/prev/view change. I would like to use that JSON object on callback to create a list of Events grouped by the startDate property.
What I've done
On Calendar update, such as new month, I was able to set up a basic ViewModel to populate a new list of events with the observable array. The only part that is missing is the group by, such as this example. Since I'm looking to group by an Event object's start date and then sort each group ascending by start date, I'm not sure of the best practices I should take, such as if it is necessary to transform my JSON data into objects. I will continue to update this post as I learn more. The reason that I am not using the linked example is because I do not understand the complete terminology behind the handler, but do understand some keywords like $root at this point.
AJAX call and requireJS module load: fullcalendar
var fullCalendar = ".calendar-module",
viewModel;
function initFullCalendar() {
$(fullCalendar).fullCalendar({
events: {
url: '/Presentation/DotGov/test/fullcalendar/GetEvents.ashx',
type: 'POST',
success: function (data) {
// bind events to KO ViewModel object
viewModel.events(data);
}
},
});
}
// requireJS module load
return {
load: function () {
viewModel = new ViewModel();
ko.applyBindings(viewModel);
initFullCalendar();
}
};
ViewModel
// Day constructor that holds the day title and an array of event objects
var Day = function() {
dayTitle = null,
events = []
}
function ViewModel() {
var self = this;
self.dates = ko.observableArray();
self.events = ko.observableArray();
self.uniqueDates = ko.computed(function () {
var allDates = ko.utils.arrayMap(self.events(), function (event) {
return new XDate(event.start).toDateString();
});
return ko.utils.arrayGetDistinctValues(allDates);
}, ViewModel);
// TODO: groupedEvents { date: /.., events: [..]}
self.groupedEvents = ko.computed(function () {
var groupedEvents = [];
var uniqueDates = self.uniqueDates();
for (var i = 0; i < uniqueDates.length; i++) {
// create new day object
var day = new Day();
day.dayTitle = uniqueDates[i];
day.events = [];
// get all events within that day
ko.utils.arrayForEach(self.events(), function (event) {
var eventDate = new XDate(event.start).toDateString();
if (eventDate == uniqueDates[i]) {
day.events[day.events.length] = event;
}
});
groupedEvents[groupedEvents.length] = day;
}
return groupedEvents;
});
}
View
<div class="calendar-module-mobile">
<div class="day-wrapper">
<p class="day-title">Monday, April 16, 2014</p> <%--the event startDate--%>
<div class="mobile-block">
<ul data-bind="foreach: events">
<li>
<a data-bind="attr: { href: eventUrl }">
<p data-bind="text: title"></p>
<span class="icon-chevron-right turquoise-icon"></span>
</a>
</li>
</ul>
</div>
</div>
</div>
Update I've updated the ViewModel with some computed observable functions. self.groupedEvents goes through the list of unique dates and returns an array of Day objects, in which each Day object contains the unique dates title and an array of Event objects (not transformed from JSON). I have to now update the View to see if it worked.