如何在选中 parent 时触发 Kendo TreeView 中 child 节点的 onCheck 事件
How to trigger the onCheck event for child nodes in Kendo TreeView, when parent is checked
我正在从服务工作者提供的数据源填充树视图:
postCreate: function () {
var self = this;
self._loadLayerConfiguration()
.then(function (data) {
self.layerConfig = data;
self._treeView = $("#LayerList").kendoTreeView({
dataValueField: "Id",
dataTextField: "Title",
checkboxes: {
checkChildren: true
},
check: self._onCheck.bind(self),
dataSource: new kendo.data.HierarchicalDataSource({ /*...*/}
})
});
});
},
如您所见,配置已设置,以便检查所有 child 元素,当检查 parent 元素时,将触发 _onCheck
方法.
此方法现在应该作用于每个正在更改的复选框:
_onCheck: function (e) {
var dataItem = this._treeView.data("kendoTreeView").dataItem(e.node);
if (!dataItem.layer && dataItem.Url !== null) { //Url is null, if this is a Group layer
//load FeatureLayer, if not loaded
//load legend, if not loaded
//add to map
//omitted for brevity
}
dataItem.layer.setVisibility(dataItem.checked);
this._checkChildren.call(this, dataItem);
},
这里的问题是,onCheck 事件只针对用户直接点击的节点触发,而不是所有受它影响的 children。
我试过递归循环遍历dataItem的所有children并手动触发检查事件,但无济于事:
_checkChildren: function (dataItem) {
var self = this;
if (dataItem.hasChildren) {
var children = dataItem.children.data();
children.forEach(function (child) {
child.set("checked", dataItem.checked);
//self._treeView.trigger("check", {
// node: self._treeView.findByUid(child.uid)
//});
if (child.hasChildren) {
//recurse
self._checkChildren.call(self, child);
}
});
}
},
效果是,事件是针对树视图中直接更改的复选框引发的,而不是它的 children。 children 只会被检查。
为受 parent 节点影响的所有 child 节点触发检查事件的正确方法是什么?
请不要被 .bind()
和 .call()
调用激怒。由于此 kendo 小部件必须在 Dojo 1.10 小部件中实现,因此结构会变得有点复杂。
根据 documentation:
这是预期的行为
Triggered after the user has checked or unchecked a checkbox. If checkChildren is true, the event is triggered after all checked states are updated.
所以事件只会触发一次,无论检查了多少children。在您的情况下,我会做的是使用解析器处理事件,以遍历所有数据项,为每个数据项调用 _onCheck
事件:
check: function(e) {
_onCheck(this.dataItem(e.node));
$(e.node).find("li").each((i, node) => _onCheck(this.dataItem(node)));
}
_onCheck: function _onCheck(dataItem) {
console.log(dataItem);
};
工作演示:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Kendo UI Snippet</title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.common.min.css"/>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.rtl.min.css"/>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.silver.min.css"/>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.mobile.all.min.css"/>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2019.1.220/js/kendo.all.min.js"></script>
</head>
<body>
<div id="treeview"></div>
<script>
let _onCheck = function _onCheck(dataItem) {
console.log(dataItem);
};
$("#treeview").kendoTreeView({
checkboxes: {
checkChildren: true
},
dataSource: [
{ text: "foo", items: [
{ text: "bar" }
] }
],
check: function(e) {
_onCheck(this.dataItem(e.node));
$(e.node).find("li").each((i, node) => _onCheck(this.dataItem(node)));
}
});
</script>
</body>
</html>
我正在从服务工作者提供的数据源填充树视图:
postCreate: function () {
var self = this;
self._loadLayerConfiguration()
.then(function (data) {
self.layerConfig = data;
self._treeView = $("#LayerList").kendoTreeView({
dataValueField: "Id",
dataTextField: "Title",
checkboxes: {
checkChildren: true
},
check: self._onCheck.bind(self),
dataSource: new kendo.data.HierarchicalDataSource({ /*...*/}
})
});
});
},
如您所见,配置已设置,以便检查所有 child 元素,当检查 parent 元素时,将触发 _onCheck
方法.
此方法现在应该作用于每个正在更改的复选框:
_onCheck: function (e) {
var dataItem = this._treeView.data("kendoTreeView").dataItem(e.node);
if (!dataItem.layer && dataItem.Url !== null) { //Url is null, if this is a Group layer
//load FeatureLayer, if not loaded
//load legend, if not loaded
//add to map
//omitted for brevity
}
dataItem.layer.setVisibility(dataItem.checked);
this._checkChildren.call(this, dataItem);
},
这里的问题是,onCheck 事件只针对用户直接点击的节点触发,而不是所有受它影响的 children。
我试过递归循环遍历dataItem的所有children并手动触发检查事件,但无济于事:
_checkChildren: function (dataItem) {
var self = this;
if (dataItem.hasChildren) {
var children = dataItem.children.data();
children.forEach(function (child) {
child.set("checked", dataItem.checked);
//self._treeView.trigger("check", {
// node: self._treeView.findByUid(child.uid)
//});
if (child.hasChildren) {
//recurse
self._checkChildren.call(self, child);
}
});
}
},
效果是,事件是针对树视图中直接更改的复选框引发的,而不是它的 children。 children 只会被检查。 为受 parent 节点影响的所有 child 节点触发检查事件的正确方法是什么?
请不要被 .bind()
和 .call()
调用激怒。由于此 kendo 小部件必须在 Dojo 1.10 小部件中实现,因此结构会变得有点复杂。
根据 documentation:
这是预期的行为Triggered after the user has checked or unchecked a checkbox. If checkChildren is true, the event is triggered after all checked states are updated.
所以事件只会触发一次,无论检查了多少children。在您的情况下,我会做的是使用解析器处理事件,以遍历所有数据项,为每个数据项调用 _onCheck
事件:
check: function(e) {
_onCheck(this.dataItem(e.node));
$(e.node).find("li").each((i, node) => _onCheck(this.dataItem(node)));
}
_onCheck: function _onCheck(dataItem) {
console.log(dataItem);
};
工作演示:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Kendo UI Snippet</title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.common.min.css"/>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.rtl.min.css"/>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.silver.min.css"/>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.mobile.all.min.css"/>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2019.1.220/js/kendo.all.min.js"></script>
</head>
<body>
<div id="treeview"></div>
<script>
let _onCheck = function _onCheck(dataItem) {
console.log(dataItem);
};
$("#treeview").kendoTreeView({
checkboxes: {
checkChildren: true
},
dataSource: [
{ text: "foo", items: [
{ text: "bar" }
] }
],
check: function(e) {
_onCheck(this.dataItem(e.node));
$(e.node).find("li").each((i, node) => _onCheck(this.dataItem(node)));
}
});
</script>
</body>
</html>