Search code examples
javascriptangularjskendo-uikendo-datasourcekendo-map

Kendo UI: One data source, two widgets


UPDATE: Here is a link to reproduce the problem

RELATED: This is another question of mine where similar problems are happening with Kendo UI Map, maybe it could help someone figure this one out! It has one failing and one working version.


I use Kendo UI's DataSource, DropDownList and Map in an Angular single-page application.

I want to use the same DataSource object for both the DropDownList and the Map. However, the Map behaves in a very unpredictable manner.

  1. When I put the DropDownList before the Map in the template, only the DropDownList gets populated. Inspecting the network traffic reveals that indeed only one request is being made. When I put the Map first, both of them get populated and two requests are made.
  2. When I don't use any promises in transport.read, but just call options.success immediately with a static value, everything works as expected. Two calls are being made.

I've been pulling my hair over this the entire work day, so any help is highly appreciated.

The data source service:

m.factory('ourDataSource', function(foo, bar, baz) {
    return new kendo.data.DataSource({
        transport: {
            read: function(options) {
                foo().then(function (result) {
                    return bar(result);
                }).then(function (result) {
                    return baz(result);
                }).then(function (result) {
                    options.success(result);
                }).catch(function (err) {
                    options.error(err);
                });
            }
        }
    });
});

The controller:

m.controller('ourController', ['ourDataSource', function(ourDataSource) {

    // set the data source of the dropdownlist
    this.ourDataSource = ourDataSource;

    // set up the map layers
    this.mapLayers = [{
        type: 'tile',
        urlTemplate: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/#= zoom #/#= y #/#= x #',
    }, {
        type: 'marker',
        dataSource: ourDataSource, // the same data source as before
        locationField: 'Position',
        titleField: 'Title'
    }];
}]);

The view:

<div ng-controller="ourController as ctrl">

    <select kendo-drop-down-list
            k-data-text-field="'Title'"
            k-data-value-field="'Title'"
            k-data-source="ctrl.ourDataSource"></select>

    <div kendo-map
         k-zoom="2"
         k-center="[1, 1]"
         k-layers="ctrl.mapLayers">
    </div>

</div>

What am I missing here?


Solution

  • I believe that this might be a bug in the Kendo UI Map widget, since the behavior occurring here isn't at all what one would expect. However, I do have a workaround solution. Rather than return the data source as a singleton object, return it as a function. This is probably not ideal, but it works.


    angular.module('ourModule', ['kendo.directives'])
    .factory('getDataSource', function ($q) {
      return function() {  // return a function that creates a new data source
        return new kendo.data.DataSource({
          transport: {
            read: function (options) {
              $q.when([
                {Position: [1, 1], Title: 'First place'},
                {Position: [10, 10], Title: 'Second place'}
              ]).then(function (result) {
                options.success(result);
              });
            }
          }
        });
      };
    })
    .controller('ourController', function (getDataSource) {
      this.ourDataSource = getDataSource();      
      this.mapLayers = [{
        type: 'tile',
        urlTemplate: '...removed for brevity...'
      }, {
        type: 'marker',
        dataSource: getDataSource(),
        locationField: 'Position',
        titleField: 'Title'
      }];
    });