Kendo UI:一个数据源,两个小部件

Posted

技术标签:

【中文标题】Kendo UI:一个数据源,两个小部件【英文标题】:Kendo UI: One data source, two widgets 【发布时间】:2016-06-17 00:52:01 【问题描述】:

更新: Here is a link to reproduce the problem

相关: This is another question of mine where similar problems are happening with Kendo UI Map, maybe it could help someone figure this one out! 它有一个失败版本和一个工作版本。


我在 Angular 单页应用程序中使用 Kendo UI 的 DataSource、DropDownList 和 Map。

我想为 DropDownList 和 Map 使用相同的 DataSource 对象。但是,地图的行为方式非常难以预测。

    当我将DropDownList 放在 模板中的地图之前,只有DropDownList 被填充。检查网络流量表明确实只有一个请求正在发出。当我首先放置地图时,它们都被填充并发出了两个请求。 当我在transport.read 中不使用任何承诺,而是立即使用静态值调用options.success 时,一切都按预期工作。正在拨打两个电话。

我整个工作日都在为此烦恼,因此非常感谢任何帮助。

数据源服务:

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);
                );
            
        
    );
);

控制器:

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'
    ];
]);

观点:

<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>

我在这里错过了什么?

【问题讨论】:

但是,您不想要两个读取请求。它是一个共享数据源,为什么要它两次请求相同的数据呢?至于为什么它不绑定到数据,我们可能需要一个复制这种行为的公共示例。很难按原样推断。 @Brett:确实,我不想要两个请求,但即使我禁用自动绑定并手动调用fetch,结果也是一样的。我觉得如果我将测试用例简化为最简单的可能会更容易弄清楚。我会看看我是否可以建立一个公开的例子。 可能是因为ourDataSource 是一个返回new 数据源对象的工厂吗?尝试将其作为单例返回。 @Brett:我会试试你的建议。同时,我写了一个例子来展示实际的问题,请看编辑后的问题! @Brett:想想看,factory 已经在 AngularJS 中创建了一个单例,除非我弄错了? 【参考方案1】:

我相信这可能是 Kendo UI 地图小部件中的一个错误,因为这里发生的行为完全不是人们所期望的。但是,我确实有一个解决方法。与其将数据源作为单例对象返回,不如将其作为函数返回。这可能并不理想,但它确实有效。


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'
  ];
);

【讨论】:

【参考方案2】:

工厂主要用于按需创建实例。看这个例子

var app = angular.module('ourModule', ['kendo.directives']);

 app.factory('dataSourceFactory', function($q) 

  function dataSourceFactory() 

  dataSourceFactory.prototype = 
   contentTypes: function() 
    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);
        );
      
     
    )
   
  ;

  return dataSourceFactory;
 );

 app.controller('ourController', ['$scope', 'dataSourceFactory',

  function($scope, dataSourceFactory) 

   var dataSourceFactory = new dataSourceFactory();

   $scope.mapLayers = [
    type: 'tile',
    urlTemplate: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/#= zoom #/#= y #/#= x #',
   , 
    type: 'marker',
    dataSource: dataSourceFactory.contentTypes(), // the same data source as before
    locationField: 'Position',
    titleField: 'Title'
   ];

   $scope.ourDataSource = dataSourceFactory.contentTypes();
  
 ]);
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.common.min.css">
  <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.rtl.min.css">
  <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.default.min.css">
  <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.mobile.all.min.css">

  <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
  <script src="http://kendo.cdn.telerik.com/2015.3.930/js/angular.min.js"></script>
  <script src="http://kendo.cdn.telerik.com/2015.3.930/js/jszip.min.js"></script>
  <script src="http://kendo.cdn.telerik.com/2015.3.930/js/kendo.all.min.js"></script>

<div ng-app="ourModule">
  
  <div ng-controller="ourController">
 		   
    <kendo-drop-down-list k-data-source="ourDataSource"
                          k-data-text-field="'Title'"
                          k-data-value-field="'Title'">
    </kendo-drop-down-list>

    <kendo-map k-zoom="2"
               k-layers="mapLayers">
    </kendo-map>
    
  </div>
</div>

查看此JSFiddle 演示

【讨论】:

以上是关于Kendo UI:一个数据源,两个小部件的主要内容,如果未能解决你的问题,请参考以下文章

如何进一步MVVM Kendo UI小部件?

Kendo UI MVC 从 MultiSelect 小部件将 Grid 绑定到 DataSource

Mvvm 支持自定义 kendo ui 小部件

更改 Kendo UI 上传小部件的文本

kendo ui 好用的小部件--grid

Kendo UI for jQuery使用教程:小部件DOM元素结构