Reputation: 182
I have a situation that has been bugging me for some time. I have a Kendo UI treeview in my project set up as described on http://demos.telerik.com/kendo-ui/web/treeview/events.html.
What I need to achieve is to say when I expand a node on the treeview, all the other nodes not in this branch should be collapsed and on this branch expanded. I have tried using the following code but unfortunately its going into an infinite loop.
<div id="example" class="k-content">
<div id="treeview" class="demo-section" style="width: 200px"></div>
<div class="demo-section">
<h3 class="title">Console log
</h3>
<div class="console"></div>
</div>
<script type="text/javascript">
$(document).ready(function() {
function onExpand(e) {
e.preventDefault();
kendoTreeView.collapse('.k-item');
kendoTreeView.expand(e.node);
}
$("#treeview").kendoTreeView({
dataSource: [
{ text: "Furniture", expanded: true, items: [
{ text: "Tables & Chairs" },
{ text: "Sofas" },
{ text: "Occasional Furniture" }
] },
{ text: "Decor", items: [
{ text: "Bed Linen" },
{ text: "Curtains & Blinds" },
{ text: "Carpets" }
] },
{ text: "Storage" }
],
expand:OnExpand
});
});
</script>
Please help.
Thanks
Upvotes: 1
Views: 9353
Reputation: 1063
I had the same issue, and I used a few solutions put together because some worked for closing other branches, but I also wanted to collapse up to my currently selected node if I clicked on a node higher up in the same tree that was already expanded.
For this behavior I used both the expand and select functions on the treeview defition:
expand: function (e) {
var parents = $(e.node).parents('[data-expanded="true"]');
//this line keeps the element you clicked on expanded as well
parents[parents.length] = $(e.node)[0];
let allOpenAbove = $(".k-item").parents('[data-expanded="true"]');
for (let i in allOpenAbove) {
for (let j in parents) {
if (allOpenAbove[i] === parents[j]) {
delete allOpenAbove[i];
}
}
}
let toCollapse = [];
allOpenAbove.each((i, elem) => {
toCollapse.push(elem);
});
this.collapse(toCollapse);
},
select: function (e) {
let openUnderneath = $(e.node).find('[data-expanded="true"]');
this.collapse(openUnderneath);
}
Upvotes: 0
Reputation: 321
OnaBai's and Logard's solutions will only work for 2nd level nodes.
This solution will work for all inner level nodes starting from 2nd level to nth level:
expand: function (e) {
var expanded = $(".k-minus");
var parents = $(e.node).parentsUntil(".k-group.k-treeview-lines");
if (parents.length <= 0 && expanded.length > 0) {
this.collapse(".k-item");
this.expand(e.node);
}
}
Edit: First solution will collapse root elements only, so I've come up with an exact solution:
expand: function (e) {
var items = $(this.element).find(".k-item:has(.k-minus)");
var parents = $(e.node).parents(".k-item");
var toCollapse = [];
items.each(function (index, item){
if ($.grep(parents, function (el) { return $(el).data("uid") == $(item).data("uid") }).length <= 0) {
toCollapse.push(item);
}
});
this.collapse(toCollapse);
}
Upvotes: 0
Reputation: 40917
As @Logard correctly points out, if you try to expand inside the OnExpand
you will enter an infinite loop since after collapsing other nodes, you want to expand current and this will trigger a new call to OnExpand
.
In order to prevent this, you should define OnExpand
handler as:
function OnExpand(e) {
if (kendoTreeView.collapsingOthers) {
kendoTreeView.collapsingOthers = false;
} else {
kendoTreeView.collapse('.k-item');
kendoTreeView.collapsingOthers = true;
kendoTreeView.expand(e.node);
}
}
This introduces a new field called collapsingOthers
that controls if I'm collapsing all nodes and programmatically expanding current. I take advantage that JavaScript allows me to expand current object dynamically adding properties.
See it here: http://jsfiddle.net/OnaBai/mVNw6/1/
Upvotes: 3
Reputation: 1513
Calling expand from the OnExpand handler will give you an infinite loop.
What if you try to let the default behaviour do the rest after you have added your collapse behaviour?
Try something like this:
$(document).ready(function() {
function onExpand(e) {
if($(".k-minus").length > 0){
$("#treeview").data("kendoTreeView").collapse('.k-item');
$("#treeview").data("kendoTreeView").expand(e)
}
}
$("#treeview").kendoTreeView({
dataSource: [
{ text: "Furniture", expanded: true, items: [
{ text: "Tables & Chairs" },
{ text: "Sofas" },
{ text: "Occasional Furniture" }
] },
{ text: "Decor", items: [
{ text: "Bed Linen" },
{ text: "Curtains & Blinds" },
{ text: "Carpets" }
] },
{ text: "Storage" }
],
expand:OnExpand
});
});
Hope this helps :)
Upvotes: 0