This is a migrated thread and some comments may be shown as answers.

RadDropDownTree custom filtering

11 Answers 280 Views
DropDownTree
This is a migrated thread and some comments may be shown as answers.
Jerome MAILLEY
Top achievements
Rank 1
Jerome MAILLEY asked on 18 Oct 2016, 02:55 PM

Hello,

I'm trying to write a custom filtering for the RadDropDownTree however i'm faced some performance issues. Here is my JS code :

function OnHierarchicalClientLoad_<%= ClientID %>(sender, eventArgs) {
            var dropDownTree = $find("<%= RadDropDownTree.ClientID %>");
 
            var typingTimer;                //timer identifier
            var doneTypingInterval = 1000;  //time in ms, 5 second for example
 
            $input = $("<input type=\"search\" class=\"search-field\" name=\"the_search\">");
 
            $input.on('keyup', function () {
                clearTimeout(typingTimer);
                typingTimer = setTimeout(function () {
                    $value = $input.val();
                    var tree = dropDownTree.get_embeddedTree();
                    tree.trackChanges();
                    var nodes = tree.get_nodes();
                    for (var i = 0; i < nodes.get_count() ; i++) {
                        var node = nodes.getNode(i);
                        SetHierarchicalComboBoxItemVisibility(node, $value);
                    }
                    tree.commitChanges();
                }, doneTypingInterval);
            });
 
            $input.on('keydown', function () {
                clearTimeout(typingTimer);
            });
 
            $("#<%= RadDropDownTree.ClientID %> .rddtHeader").append($input);
                
        }  
 
         function SetHierarchicalComboBoxItemVisibility(node, filter) {
             var isVisible = false;
             var allNodes = node.get_allNodes();
             for (var i = 0; i < allNodes.length; i++) {
                 var childNode = allNodes[i];
                 isVisible = SetHierarchicalComboBoxItemVisibility(childNode, filter);
             }
             isVisible = (isVisible || filter == "" || node.get_text().toLowerCase().indexOf(filter.toLowerCase()) != -1);
             node.get_element().style.display = isVisible ? "" : "none"; //Workaround
             //node.set_visible(isVisible); //performance too slow
             return isVisible;
         }

 

As you can see I used a workaround because the set_visible() function is too slow when there is a bit amount of nodes (some thousands). It seems that it use some functions that do some css stuffs on sibling node as ensureAppearance().

So I have two questions :

- Is there a way to optimise the use of set_visible() function on a huge amount of nodes ?

- Else, is my workaround may cause problems?

 

Thank you,

11 Answers, 1 is accepted

Sort by
0
Nencho
Telerik team
answered on 21 Oct 2016, 08:14 AM
Hello Jerome,

As you had well observed, the set_visible method ensures that not only the current node will be hidden, but its child nodes as well. Also, it ensures that if there are any child nodes to hide - the toggle element of the parent node will also be hidden.

This is why, it requires more time. It's up to you and your scenario to evaluate whether this approach with the styling is applicable. In other words, if you don't have an hierarchical structure of the nodes - it will be. Otherwise, I suggest you to use the set_visible method, which is tested and we can grantee that no unexpected behavior will be caused by its usage.

On a side note, please keep in mind that such customization are not supported and once implemented they become developers responsibility.

Regards,
Nencho
Telerik by Progress
Check out the new UI for ASP.NET Core, the most complete UI suite for ASP.NET Core development on the market, with 60+ tried-and-tested widgets, based on Kendo UI.
0
Jerome MAILLEY
Top achievements
Rank 1
answered on 25 Oct 2016, 10:03 AM

Hello Nencho,

I understand your suggestion about I should use the set_visible method and it's precisly what I wanted to do. However, due to performance issues I cannot ignore, I need to find another solution. Please understand I cannot let the user waits a couple of secs (with browser frozen) each time he makes a search.... 

Plus, I also noticed that RadDropDownTreeNode set_visible is not the only client function which may be slow. Each time, I use on client side set_enabled on RadDropDownTree it spends even more time. For about 10 RadDropDownTrees with some hundred of node inside, it spends about 20 seconds to makes them disabled. I thought that RadDropDownTree set_enabled function just avoids the dropdown to open but it seems that it also set all the tree node enable property... 

Please try to understand that it's not a possible solution for us to let the user browser freeze in this way...

Thanks,

0
Veselin Tsvetanov
Telerik team
answered on 28 Oct 2016, 08:50 AM
Hi Jerome,

We have reviewed your implementation and we were unable to find part of it that would possibly cause major issues with the control functionality. However, note that if yo you have hierarchical data and you hide a parent node that does not meet the filtering string, but you have a child node that does meet the filtering criteria, you wont be able to view that child node too.

In order to show the parent nodes of visible nodes, I would suggest you to introduce â€‹isInnerVisible variable to your â€‹SetHierarchicalComboBoxItemVisibility() function:
function SetHierarchicalComboBoxItemVisibility(node, filter) {
    var isVisible = false;
    var isInnerVisible = false;
    var allNodes = node.get_allNodes();
    for (var i = 0; i < allNodes.length; i++) {
        var childNode = allNodes[i];
        isVisible = SetHierarchicalComboBoxItemVisibility(childNode, filter);
        isInnerVisible = isInnerVisible || isVisible;
    }
    isVisible = (isVisible || isInnerVisible || filter == "" || node.get_text().toLowerCase().indexOf(filter.toLowerCase()) != -1);
    node.get_element().style.display = isVisible ? "" : "none";
    return isVisible;
}

As my colleague Nencho pointed out, you should keep in mind that this is a customization of the control functionality.

Regards,
Veselin Tsvetanov
Telerik by Progress
Check out the new UI for ASP.NET Core, the most complete UI suite for ASP.NET Core development on the market, with 60+ tried-and-tested widgets, based on Kendo UI.
0
Jerome MAILLEY
Top achievements
Rank 1
answered on 28 Oct 2016, 02:43 PM

Hi Veselin,

Indeed, I noticed and fixed that issue in my code a couple of days ago. My code is faster, however it does not hide the dropdown icon in case there is no child item.

Moreover, is there a way to make the radDropDownTree.set_enabled() faster? As I said before, when there is some raddropdowntrees in the same page, it spends a lot of time to make them disabled.

 

Regards,

0
Veselin Tsvetanov
Telerik team
answered on 01 Nov 2016, 03:36 PM
Hello Jerome,

As you correctly noticed, the custom implementation discussed does not cover all the edge cases, that the built-in functionality does. Performing all the needed checks is one of the reasons for the slower performance of the set_visivble() method.

Concerning the set_enabled() issue, I have created a sample page, implementing a scenario with 10 RadDropDownLists, each with 500 items. By clicking on the "Disable" button the user could disable all of them. Running it locally on Chrome, this takes less than a second to do that. Could you, please modify this sample, so it reproduces the problem observed and send it back to us?

Regards,
Veselin Tsvetanov
Telerik by Progress
Check out the new UI for ASP.NET Core, the most complete UI suite for ASP.NET Core development on the market, with 60+ tried-and-tested widgets, based on Kendo UI.
0
Jerome MAILLEY
Top achievements
Rank 1
answered on 07 Nov 2016, 03:36 PM

Hello Veselin,

Indeed, when I execute your sample page the set_enabled function is fast. However, in your project, there is just one level in each RadDropDownTree. I updated your code to build tree levels on each treeview . Plus I added the Checkbox feature which increase a lot the execution time of the set_enabled function. These two modifications make your page closer to my needs. Please update your project with the following code and let me know if you are able to reproduce the problem :

protected void Page_Load(object sender, EventArgs e)
        {
            DataTable data = new DataTable();
            data.Columns.Add("value");
            data.Columns.Add("text");
            data.Columns.Add("ID");
            data.Columns.Add("ParentID");
            int id = 0;
            List<DataRow> rootRow = new List<DataRow>();
            for (int j = 0; j < 5; j++)
            {
                DataRow currentRow = data.NewRow();
                currentRow["text"] = "Country " + j;
                currentRow["value"] = "Value " + j;
                currentRow["ID"] = id;
                rootRow.Add(currentRow);
                id++;
            }
 
            List<DataRow> nodeRow = new List<DataRow>();
            foreach (var row in rootRow)
            {
                data.Rows.Add(row);
                for (int i = 0; i < 10; i++) {
                    DataRow currentRow = data.NewRow();
                    currentRow["text"] = "Country " + row["ID"] + i;
                    currentRow["value"] = "Value " + row["ID"] + i;
                    currentRow["ID"] = id;
                    currentRow["ParentID"] = row["ID"];
                    nodeRow.Add(currentRow);
                    id++;
                }
            }
 
            foreach (var row in nodeRow)
            {
                data.Rows.Add(row);
                for (int i = 0; i < 10; i++)
                {
                    DataRow currentRow = data.NewRow();
                    currentRow["text"] = "Country " + row["ID"] + i;
                    currentRow["value"] = "Value " + row["ID"] + i;
                    currentRow["ID"] = id;
                    currentRow["ParentID"] = row["ID"];
                    data.Rows.Add(currentRow);
                    id++;
                }
            }
 
            for (int i = 1; i <= 10; i++)
            {
                var dropDownTreeID = "RadDropDownTree" + i;
                var tree = (RadDropDownTree)Page.FindControl(dropDownTreeID);
                tree.CheckBoxes = DropDownTreeCheckBoxes.SingleCheck;
                tree.DataTextField = "text";
                tree.DataValueField = "value";
                tree.DataFieldID = "ID";
                tree.DataFieldParentID = "ParentID";
                tree.DataSource = data;
                tree.DataBind();
 
            }
 
        }

 

0
Veselin Tsvetanov
Telerik team
answered on 09 Nov 2016, 03:56 PM
Hello Jerome,

I have tested the same page with your suggested implementation (attached). In Crome 54 browser the 10 RadDropDownLists are disabled for around 200 ms. You could see running the test here.

Regards,
Veselin Tsvetanov
Telerik by Progress
Check out the new UI for ASP.NET Core, the most complete UI suite for ASP.NET Core development on the market, with 60+ tried-and-tested widgets, based on Kendo UI.
0
Jerome MAILLEY
Top achievements
Rank 1
answered on 09 Nov 2016, 10:10 PM

Hello Veselin,

I forgot to precise that I use IE 11 for my tests. Could you please run your project on this browser and tell me if you have got the same results?

Thank you,

0
Veselin Tsvetanov
Telerik team
answered on 10 Nov 2016, 04:14 PM
Hi Jerome,

Thank you for the additional information provided. Based on that I was able to reproduce the performance issue both in IE 11 and Edge. 

After a careful review of the control functionality, we can confirm that the discussed is a performance issue. Therefore, I have included it in our backlog. I have also created a bug item in our Feedback portal, where you could track the bug status.

As a token of gratitude for helping us to isolate the issue, I have updated your Telerik points.

Going back to the discussed example, I could suggest you the following change to the disable function of the DropDownTrees:
for (var i = 1; i <= 10; i++) {
    var tree = $find('RadDropDownTree' + i);
 
    // This disables the Tree
    tree._enabled = false;
 
    var $element = $telerik.$(tree.get_element),
        $innerDiv = $element.find('.rddtInner'),
        $clearButton = $element.find('.rddtClearButton');
 
    // This adds the needed attributes and classes on the Tree elemnts,
    // so they appear disabled on the screen
    $innerDiv.addClass('rddtDisabled');
    $clearButton.attr('disabled', 'disabled');
    tree.closeDropDown();
    tree._toggleAttribute(tree._element, true, "tabindex", null);
}

Attached you will find a modified sample page, implementing the above.

Regards,
Veselin Tsvetanov
Telerik by Progress
Check out the new UI for ASP.NET Core, the most complete UI suite for ASP.NET Core development on the market, with 60+ tried-and-tested widgets, based on Kendo UI.
0
Jerome MAILLEY
Top achievements
Rank 1
answered on 18 Nov 2016, 10:04 AM

Hi Veselin,

Thank you for the workaround. Performance is much better with this. 

I saw the bug created on your Feedback portal. However you didn't talk about set_visible() function on RadDropDownTreeNode with is also too slow on IE when RadDropDownTree contains a lot of nodes. Please don't forget that it's the first problem I described on this thread and I still not have a good workaround to deal with it.

Thanks,

0
Veselin Tsvetanov
Telerik team
answered on 22 Nov 2016, 10:08 AM
Hello Jerome,

The set_visible() functionality of the RadDropDownTree requires considerable DOM manipulations, in order to guarantee correct rendering of all nodes, their status, the expanding capabilities and so on. Therefore, this functionality heavily relies on the browser's JavaScript engine to process the manipulations fast. In consequence, hiding all the root nodes in a DropDownTree with 500 root nodes may require around 250 ms on Google Chrome, while the same operation may require around 5 seconds in IE.

The main difference with the set_enabled() scenario is the fact, that when disabling the entire DropDownTree, we do not need to disable the nodes one by one (which causes the performance issue in our internal implementation), while here, we have to iterate over all nodes and make sure those that remain visible render correctly. Therefore, the set_visible() performance issue is considered to be an IE browser limitation and not a bug in the control's functionality.

Regards,
Veselin Tsvetanov
Telerik by Progress
Telerik UI for ASP.NET AJAX is ready for Visual Studio 2017 RC! Learn more.
Tags
DropDownTree
Asked by
Jerome MAILLEY
Top achievements
Rank 1
Answers by
Nencho
Telerik team
Jerome MAILLEY
Top achievements
Rank 1
Veselin Tsvetanov
Telerik team
Share this question
or