Dynamically Refreshing Resources and Schedule Events in Timeline View

3 posts, 0 answers
  1. Ralph Quintero
    Ralph Quintero avatar
    5 posts
    Member since:
    Jan 2008

    Posted 08 Feb Link to this post

    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. Vladimir Iliev
    Admin
    Vladimir Iliev avatar
    2172 posts

    Posted 10 Feb Link to this post

    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!
     
  3. Kendo UI is VS 2017 Ready
  4. Ralph Quintero
    Ralph Quintero avatar
    5 posts
    Member since:
    Jan 2008

    Posted 10 Feb in reply to Vladimir Iliev Link to this post

    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

Back to Top