我首先要说的是我根本不知道这是否可行,但我正在阅读Kendo UI文档,并试图找出如何至少尝试一下,但是我在制作自定义绑定时遇到了很多困难。这是我仍在处理的另一个问题的后续问题,该问题已发布here。如果这不是一个合适的问题,请告诉我,我会将其关闭或改写。在这一点上,我真的很迷茫和迷茫。
根据我的理解,基于我被告知和尝试的内容,剑道无法绑定到关联数组,不是因为数据不好,而是因为它是一组对象,每个都作为一个单独的单独实体 - 在正常情况下,数组会有所不同,并包含长度属性,以及其他一些函数 array 原型,可以通过它进行迭代。
所以我试图猜想如何解决这个问题。我成功地获得了认为的功能解决方法。我作为"思考"因为我对Javascript的经验太缺,无法真正了解这样做的后果(性能,稳定性等)
这就是我的所作所为;
<script type="text/x-kendo-template" id="display-items-many">
# for(var key in data) { #
# if (data.hasOwnProperty(key) && data[key].hasOwnProperty("Id")) { #
<tr>
<td>
<strong>#= data[key].Id #</strong>
</td>
<td class="text-right">
<code>#= data[key].Total #</code>
</td>
</tr>
# } #
# } #
</script>
<table class="table borderless table-hover table-condensed" data-bind="source: Associative data-template="display-items-many">
</table>
现在对我来说,立即离开,这给了我运作的幻觉。所以我想更多地考虑如何解决这个问题......
我想创建一个名为binding
的新repeat
。此绑定的目标如下;
为给定根对象中符合给定条件的对象的每个实例重复模板
在我的脑海中,这将起到这样的作用;
<div data-template="repeater-sample" data-bind="repeat: Associative"></div>
<script type="text/x-kendo-template" id="repeater-sample">
<div> ${ data.Id }</div>
</script>
条件将是一个简称为 _associationKey
的属性。因此,从理论上讲,以下内容将起作用。
$.ajax({
// get data from server and such.
}).done(function(results){
// simple reference to the 'associative array' for easier to read code
var associative = results.AssociativeArray;
// this is a trait that everything in the 'associative array' should have to match
// this is purely, purely an example. Obviously you would use a more robust property
var match = "Id";
// go through the results and wire up the associative array objects
for(var key in associative ) {
if(associative.hasOwnProperty(key) && associative[key].hasOwnProperty(match)) {
associative[key]._associationKey = 10; // obviously an example value
}
}
// a watered down example implementation, obviously a real use would be more verbose
viewModel = kendo.observable({
// property = results.property
// property = results.property
associativeArray = associative
});
kendo.bind('body', viewModel);
});
到目前为止,这实际上似乎工作得很好,但我必须使用内联脚本来硬编码模板中的逻辑。这就是我想要避免的。
最大的问题是我对telerik的自定义绑定文档(可用here)感到非常困惑。我确实有他们的例子可以借鉴,是的 - 但是我对它如何与对象进行交互有点困惑。我会尝试来解释,但我很失落,可能很难。
这就是telerik为示例自定义绑定提供的内容,并且我已经对空间问题进行了一些修剪;
<script>
kendo.data.binders.repeater = kendo.data.Binder.extend({
init: function(element, bindings, options) {
//call the base constructor
kendo.data.Binder.fn.init.call(this, element, bindings, options);
var that = this;
// how do we interact with the data that was bound?
}
});
</script>
基本上就是我迷失的地方。我有一个很大的脱节,弄清楚如何与实际的##;关联数组进行交互&#34;使用data-bind="repeat: associativeArray"
所以......
我一直在挖掘剑道源代码,这就是我到目前为止 - 以source
绑定为例......但我还是没有得到正确的结果。不幸的是,这会带来一些问题;
某些功能是kendo的内部功能,我不知道如何在不重写的情况下访问它们。虽然我有源并可以做到这一点,但我更喜欢制作与版本无关的代码,以便它可以插入&#34;插入&#34;到较新的版本
我完全迷失了很多这样做的事情。我基本上制作了source
绑定的副本,并尽可能用我自己的语法替换它,因为这个概念基本上是相同的。 我无法弄清楚测试在哪里进行资格审核,如果有意义的话。
我在这里有一个很大的逻辑断开 - 理想情况下应该一些的地方我基本上可以说... If the current item that kendo is attempting to render in a template matches a criteria, render it. If not, pass it over
然后另一个地方,我告诉它迭代关联数组中的每个对象&#39;以便达到我测试的程度。
我觉得强迫for
循环在这里实际上会让这个火太多次了,而且我很迷茫。非常感谢任何帮助。
kendo.data.binders.repeat = kendo.data.Binder.extend({
init: function(element, bindings, options) {
kendo.data.Binder.fn.init.call(this, element, bindings, options);
var source = this.bindings.repeat.get();
if (source instanceof kendo.data.DataSource && options.autoBind !== false) {
source.fetch();
}
},
refresh: function(e) {
var that = this,
source = that.bindings.repeat.get();
if (source instanceof kendo.data.ObservableArray|| source instanceof kendo.data.DataSource) {
e = e || {};
if (e.action == "add") {
that.add(e.index, e.items);
} else if (e.action == "remove") {
that.remove(e.index, e.items);
} else if (e.action != "itemchange") {
that.render();
}
} else {
that.render();
}
},
container: function() {
var element = this.element;
if (element.nodeName.toLowerCase() == "table") {
if (!element.tBodies[0]) {
element.appendChild(document.createElement("tbody"));
}
element = element.tBodies[0];
}
return element;
},
template: function() {
var options = this.options,
template = options.template,
nodeName = this.container().nodeName.toLowerCase();
if (!template) {
if (nodeName == "select") {
if (options.valueField || options.textField) {
template = kendo.format('<option value="#:{0}#">#:{1}#</option>',
options.valueField || options.textField, options.textField || options.valueField);
} else {
template = "<option>#:data#</option>";
}
} else if (nodeName == "tbody") {
template = "<tr><td>#:data#</td></tr>";
} else if (nodeName == "ul" || nodeName == "ol") {
template = "<li>#:data#</li>";
} else {
template = "#:data#";
}
template = kendo.template(template);
}
return template;
},
add: function(index, items) {
var element = this.container(),
parents,
idx,
length,
child,
clone = element.cloneNode(false),
reference = element.children[index];
$(clone).html(kendo.render(this.template(), items));
if (clone.children.length) {
parents = this.bindings.repeat._parents();
for (idx = 0, length = items.length; idx < length; idx++) {
child = clone.children[0];
element.insertBefore(child, reference || null);
bindElement(child, items[idx], this.options.roles, [items[idx]].concat(parents));
}
}
},
remove: function(index, items) {
var idx, element = this.container();
for (idx = 0; idx < items.length; idx++) {
var child = element.children[index];
unbindElementTree(child);
element.removeChild(child);
}
},
render: function() {
var source = this.bindings.repeat.get(),
parents,
idx,
length,
element = this.container(),
template = this.template();
if (source instanceof kendo.data.DataSource) {
source = source.view();
}
if (!(source instanceof kendo.data.ObservableArray) && toString.call(source) !== "[object Array]") {
source = [source];
}
if (this.bindings.template) {
unbindElementChildren(element);
$(element).html(this.bindings.template.render(source));
if (element.children.length) {
parents = this.bindings.repeat._parents();
for (idx = 0, length = source.length; idx < length; idx++) {
bindElement(element.children[idx], source[idx], this.options.roles, [source[idx]].concat(parents));
}
}
}
else {
$(element).html(kendo.render(template, source));
}
}
});
答案 0 :(得分:2)
我建议在associative array
中将传输array
转换为更简单的解决方案。这非常简单(对大多数情况而言)可以解决您的问题。
假设您从服务器收到以下关联数组:
{
"One" : { Name: "One", Id: "id/one" },
"Two" : { Name: "Two", Id: "id/two" },
"Three" : { Name: "Three", Id: "id/three" }
}
这是存储在名为input
的变量中。将其从associative
转换为无关联就像以下一样简单:
var output = [];
$.each(input, function(idx, elem) {
elem.index = idx;
output.push(elem);
});
现在,您在output
中有一个等效数组,我将索引字段保存到一个名为index
的字段中,用于关联数组的每个元素。
现在,您可以使用开箱即用的代码显示从服务器收到的数据。
在此处查看此行动:http://jsfiddle.net/OnaBai/AGfWc/
您甚至可以使用KendoUI DataSource
来使用DataSource.schema.parse
方法检索和转换数据:
var dataSource = new kendo.data.DataSource({
transport: {
read: ...
},
schema : {
parse: function (response) {
var output = [];
$.each(response, function(idx, elem) {
elem.index = idx;
output.push(elem);
});
return output;
}
}
});
你的模型将是:
var viewModel = new kendo.data.ObservableObject({
Id: "test/id",
Associative: dataSource
});
您可以在此处看到它:http://jsfiddle.net/OnaBai/AGfWc/1/