Пользовательский интерфейс Kendo: один источник данных, два виджета
ОБНОВЛЕНИЕ: Вот ссылка, чтобы воспроизвести проблему
СВЯЗАННЫЙ: Это еще один мой вопрос, где подобные проблемы возникают с Kendo UI Map, возможно, это может помочь кому-то разобраться в этом! У него одна неисправная и одна рабочая версия.
Я использую DataSource, DropDownList и Map пользовательского интерфейса Kendo в одностраничном приложении Angular.
Я хочу использовать один и тот же объект DataSource для DropDownList и Map. Однако карта ведет себя очень непредсказуемым образом.
- Когда я помещаю 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>
Что мне здесь не хватает?
2 ответа
Я считаю, что это может быть ошибкой в виджете Kendo UI Map, поскольку происходящее здесь поведение совсем не то, что можно было бы ожидать. Тем не менее, у меня есть обходное решение. Вместо того, чтобы возвращать источник данных как одноэлементный объект, верните его как функцию. Это, вероятно, не идеально, но это работает.
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'
}];
});
Фабрика в основном используется для создания экземпляров по требованию. Смотрите этот пример
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