This is a migrated thread and some comments may be shown as answers.

Dynamically Refreshing Resources and Schedule Events in Timeline View

2 Answers 872 Views
Scheduler
This is a migrated thread and some comments may be shown as answers.
Ralph Quintero
Top achievements
Rank 1
Ralph Quintero asked on 08 Feb 2016, 08:23 PM

Greets,

I am currently running into an issue when working with the Kendo UI Scheduler and attempting to use two data sources (one which depends upon another) for both the resources and the scheduling events.

I have created a mock service which returns a random number of resources and a random number of events, each event tied to a specific resource.  The JSON for a single event (in an event array) and the resource itself looks as follows for my 'mock' service:

[{
  "resourceId":1,
  "timelineSchedules":[{
    "sessionId":1,
    "start":"2016-02-08T03:00:00",
    "end":"2016-02-08T09:00:00",
    "status":14
  }]
}]

 My HTML page contains only one simple <div> element to host the calendar, as follows:

<div id="calendar"></div>

 

Now, here is an example of the JavaScript that I am using to read from the service (pared down to what is required), then also set the data in the secondary data source:

 

(function($, kendo, undefined) {
   var schedulingBlockDataSource = new kendo.data.SchedulerDataSource(),
       timelineDataSource = new kendo.data.SchedulerDataSource({
          type: "json",
          batch: true,
          transport: {
             read: {
                type: "GET",
                dataType: "json",
                url: "http://localhost/jsnovaservices/api/timeline",
                contentType: "application/json; charset=UTF-8",
             }
          },
          change: function(e) {
             var timelineData = this.data(),
                 schedules = new kendo.data.ObservableArray([]);
  
             $.each(this.data(), function(rowIndex, resourceRow) {
                $.each(resourceRow.timelineSchedules, function(index, element) {
                   schedules.push(new kendo.data.SchedulerEvent({
                      id: element.sessionId,
                      title: "Test",
                      description: "Test",
                      resourceId: resourceRow.resourceId,
                      start: new Date(element.start),
                      end: new Date(element.end)
                   }));
                });
             });
  
             schedulingBlockDataSource.data(schedules);
         },
         schema: {
            data: function(timelineData) {
               var resourceList = new kendo.data.ObservableArray([]);
          
               $.each(timelineData, function(index, element) {
                  resourceList.push({
                     value: element.resourceId,
                     resourceId: element.resourceId,
                     text: "Room " + element.resourceId,
                     timelineSchedules: element.timelineSchedules
               });
            });
  
            return resourceList;             
        }
      }
   });
    
   $(document).ready(function() {
      var scheduler = $("#calendar").kendoScheduler({
         dataSource: schedulingBlockDataSource,
         navigate: function(e) {
            timelineDataSource.read();
         },
         views: ["timeline"],
         group: {
           resources: ["Rooms"],
           orientation: "vertical"
         },
         resources:[ {
            field: "resourceId",
            name: "Rooms",
            dataSource: timelineDataSource
         }]    
      }).getKendoScheduler();
   });  
})(jQuery, window.kendo);

 This works for a couple of time when doing navigation (using the 'Today' to navigate since I'm returning all mock scheduling events with the current date); however, eventually it will get the following error:

 

kendo.all.js:79184 Uncaught TypeError: Cannot read property '_continuousEvents' of undefined
SchedulerView.extend._renderEvents    @ kendo.all.js:79184    if (!group._continuousEvents) {
SchedulerView.extend.render           @ kendo.all.js:78985
DataBoundWidget.extend.refresh        @ kendo.all.js:82705
n.isFunction.f                        @ jquery.min.js:2
Class.extend.trigger                  @ kendo.all.js:124
Observable.extend._process            @ kendo.all.js:6869
Observable.extend.data                @ kendo.all.js:6086
kendo.data.SchedulerDataSource.change @ scheduler.js:36

It appears that there is some type of synchronization going on within the calendar in which the events and the resources themselves are being rendered in the view, but they are out of sync.  The service to which I am trying to fit the calendar to returns the resource and scheduling information, so only one service call is needed, but I need to "reshape" the data for both the resource list and the scheduling events from the same service results.

Is there something that I need to do in order to make sure that the refresh of the Scheduler is synchronized with the update and reshaping of the data for both my resource list and scheduler events?  I am already going to extend the TimelineView with my own implementation, is there something I can do there or is this something that can be handled from within the data source itself?  I need to be able to dynamically change the resource list and events without having to recreate the entire Scheduler.  Any help would be appreciated.

 

 

2 Answers, 1 is accepted

Sort by
0
Vladimir Iliev
Telerik team
answered on 10 Feb 2016, 11:12 AM
Hello Ral,

As the described solution is considered as a custom one currently I could only suggest to try parsing the data using the dataSource "schema.parse" function and before returning the data to the scheduler to set it's resources dataSource (similar to this demo). 

Regards,
Vladimir Iliev
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Ralph Quintero
Top achievements
Rank 1
answered on 10 Feb 2016, 03:37 PM

Hi Vladimir,

Unfortunately, that approach did not work for me.  The real issue, it seems, is needing to update both the resource list (which can change drastically) and the schedule list.  Attempting to clear either one resulted in various exceptions depending upon the order in which the clear occurred.

However, I did find a solution that worked.  Basically I needed to destroy, clear the HTML child elements of my Scheduler <div> and then reconstruct a new Scheduler.  (There was another post brought to my attention which did this to modify the resource list).  I created a model which contained a single DataSource and queried that DataSource directly from within my model, then used the resulting data to create a resource and schedule array internally.  I provided a callback so that when my data had been read and processed, I could reconstruct a new Scheduler and use those two arrays to initialize the DataSources for both the scheduler DataSource and the resources DataSource.  Below is the result which appears to work great with no problems:

(function ($, kendo, undefined) {
 
    var timeline = {
        _resources: [],
        _schedules: [],
        _callback: null,
        _timelineDataSource: new kendo.data.DataSource({
            type: "json",
            transport: {
                read: {
                    type: "GET",
                    dataType: "json",
                    url: "http://localhost/jsnovaservices/api/timeline",
                    contentType: "application/json; charset=UTF-8"
                }
            }
        }),
        resources: function () { return this._resources; },
        schedules: function () { return this._schedules; },
        getSchedules: function (callback) {
            var self = this;
 
            self._resources.splice(0, self._resources.length);
            self._schedules.splice(0, self._schedules.length);
 
            $.when(self._timelineDataSource.read()).done(function () {
 
                var data = self._timelineDataSource.data();
 
                if (data) {
                    $.each(data, function (index, element) {
                        self._resources.push({
                            resourceId: element.resourceId,
                            text: "Room " + element.resourceId,
                            timelineSchedules: element.timelineSchedules
                        });
                    });
 
                    $.each(data, function (rowIndex, resourceRow) {
                        $.each(resourceRow.timelineSchedules, function (index, element) {
                            self._schedules.push(new kendo.data.SchedulerEvent({
                                id: element.sessionId,
                                title: "Test",
                                description: "Test",
                                resourceId: resourceRow.resourceId,
                                start: new Date(element.start),
                                end: new Date(element.end)
                            }));
                        });
                    });
                }
 
                if (callback && $.isFunction(callback)) {
                    callback(self);
                }
            });
        }
    };
 
    var refreshCalendar = function (data) {
        var schedulerElement = $("#calendar"),
            scheduler = schedulerElement.getKendoScheduler();
 
        if (scheduler) {
            scheduler.destroy();
            schedulerElement.empty();
        }
 
        $("#calendar").kendoScheduler({
            dataSource: data.schedules(),
            navigate: function (e) {
                timeline.getSchedules(function (data) {
                    refreshCalendar(data);
                });
            },
            views: [{ type: kendo.ui.ExtendedTimelineView, title: "Extended Timeline View" }],
            group: {
                resources: ["Rooms"],
                orientation: "vertical"
            },
            resources: [{
                field: "resourceId",
                name: "Rooms",
                dataValueField: "resourceId",
                dataSource: data.resources()
            }]
        });
    }
 
    $(document).ready(function () {
        timeline.getSchedules(function (data) {
            refreshCalendar(data);
        });
    });
 
})(jQuery, window.kendo);
 
//@ sourceURL=scheduler.js
//# sourceURL=scheduler.js

Tags
Scheduler
Asked by
Ralph Quintero
Top achievements
Rank 1
Answers by
Vladimir Iliev
Telerik team
Ralph Quintero
Top achievements
Rank 1
Share this question
or