jquery - Group Events by Date using KnockoutJS -


update: provided best answer problem. feel free improve readability and/or efficiency.


problem: using fullcalendar.io in requirejs set up, event objects (received ajax call .ashx handler) populated on calendar on every next/prev/view change. use json object on callback create list of events grouped startdate property.

what i've done
on calendar update, such new month, able set basic viewmodel populate new list of events observable array. part missing group by, such this example. since i'm looking group event object's start date , sort each group ascending start date, i'm not sure of best practices should take, such if necessary transform json data objects. continue update post learn more. reason not using linked example because not understand complete terminology behind handler, understand keywords $root @ point.

ajax call , 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 ko viewmodel object                     viewmodel.events(data);                 }             },     }); }  // requirejs module load return {     load: function () {          viewmodel = new viewmodel();         ko.applybindings(viewmodel);          initfullcalendar();     } }; 

viewmodel

// day constructor holds day title , 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();          (var = 0; < uniquedates.length; i++) {             // create new day object             var day = new day();             day.daytitle = uniquedates[i];             day.events = [];              // events within 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 viewmodel computed observable functions. self.groupedevents goes through list of unique dates , returns array of day objects, in each day object contains unique dates title , array of event objects (not transformed json). have update view see if worked.

answering own question here instead of continuing update question. feel free leave answer, , if think better solution, give best answer.

fullcalendar: ajax call , events

$(fullcalendar).fullcalendar({     header: {         left: '',         center: 'month,agendaweek,agendaday',         right: 'prev,title,next'     },     titleformat: {         agendaweek: "(m/dd/yyyy)",         agendaday: "dddd mmmm d, yyyy"     },     mintime: "07:00:00",     maxtime: "19:00:00",     fixedweekcount: false,     alldayslot: false,     editable: false,     eventlimit: {         'month': 3,         'default': true  // gives default value other views     },     events: {         url: '/presentation/test/fullcalendar/getevents.ashx',         type: 'post',         success: function (data) {              // don't render event if not in month (sometimes events @ end or beggining of prev/next month rendered)             (var = 0; < data.length; i++) {                 if ((new date(data[i].start).getutcmonth()) != (new date($(fullcalendar).fullcalendar('getview').start).getutcmonth())) {                     data.splice(i, 1);                 }             }              //var parsed = json.parse(data);             viewmodel.events(data);     // bind events ko viewmodel         }     },     /* event handlers */     eventclick: function(calevent, jsevent, view) {          // hide overlays         $('.fc-event').find('.overlay').fadeout();          var $overlay = $(jsevent.currenttarget).find('.overlay');         $overlay.show();          jsevent.stoppropagation();         return false;     },     eventrender: function (event, element, view) {    // fired on loading eventlimit popup.. check event          // if loading event on view         if (event.startdisplaydate == undefined) {             // format start , end dates             event.startdisplaydate = new xdate(event.start._i).tostring("ddd, mmmm d, h(:mm)tt");             event.enddisplaydate = new xdate(event.end._i).tostring("ddd, mmmm d, h(:mm)tt");         } else         {             // rendering event again, inside limitclick popover (todo: find better way)             event.overlayclasses = "position-left";         }          element.append(popuptemplate(event));     },     viewrender: function (view, element) {         $(fullcalendar).fullcalendar('refetchevents');  // refetch events on view change     } }); 

viewmodel , objects

var event = function (event) {     this.eventid = event.id;     this.eventtitle = event.title;     this.startdate = event.start;     this.starthour = new xdate(event.start).tostring("(h:mm)t");     this.enddate = event.end;     this.eventurl = event.eventurl; }  // day constructor holds day title , array of event objects var day = function() {     daytitle = null,     events = [] }  function viewmodel() {     var self = this;      self.dates = ko.observablearray();     self.events = ko.observablearray(); // todo: sort date      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);      // groupedevents { date: /.., events: [..]}     self.groupedevents = ko.computed(function () {          var groupedevents = [];         var uniquedates = self.uniquedates();          (var = 0; < uniquedates.length; i++) {             // create new day object             var day = new day();             day.daytitle = uniquedates[i];             day.events = [];              // events within day             ko.utils.arrayforeach(self.events(), function (event) {                 var eventdate = new xdate(event.start).todatestring();                 if (eventdate == uniquedates[i]) {                     day.events[day.events.length] = new event(event);                 }             });             groupedevents[groupedevents.length] = day;         }         return groupedevents;     }); } 

view

<div class="calendar-module-mobile">     <div data-bind="foreach: groupedevents">         <div class="day-wrapper">             <p data-bind="text: daytitle" class="day-title"></p>             <%--the event startdate--%>             <div class="mobile-block">                 <ul data-bind="foreach: events">                     <li>                         <span data-bind="text: starthour"></span>                         <a data-bind="attr: { href: eventurl }">                             <p data-bind="text: eventtitle"></p>                             <span class="icon-chevron-right turquoise-icon"></span>                         </a>                     </li>                 </ul>             </div>         </div>     </div> </div> 

Comments

Popular posts from this blog

matlab - "Contour not rendered for non-finite ZData" -

delphi - Indy UDP Read Contents of Adata -

javascript - Any ideas when Firefox is likely to implement lengthAdjust and textLength? -