Stewart Mbofana
Stewart Mbofana

Reputation: 182

Kendo UI Treeview collapse all items and only expand current node

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

Answers (4)

tkd_aj
tkd_aj

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

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

OnaBai
OnaBai

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

Logard
Logard

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

Related Questions