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

[Solved] conditionally check child nodes

3 Answers 259 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Steve
Top achievements
Rank 1
Steve asked on 03 Feb 2010, 04:20 AM
I have a treeview, with checkboxes=true, tristatecheckboxes=true, and want to use checkchildnodes=true, but, I want to not have certain child nodes, with a certain attribute value, to be auto-checked, these nodes are always at the bottom/lowest level of the tree.

if I try to spin my own checking logic, with checkchildnodes=false, the tristate checking stuff does not work right, I check a higher level node, and it goes full check, it seems there is no method of setting the check state to indeterminate, so I can only check, or uncheck the higher level nodes, so, it seems I can't conditionally set them to indeterminate if I find some nodes as children I don't want to check.

and, unchecking nodes is proving problematic as well, higher level nodes don't uncheck as expected when checkchildnodes=false, and child nodes are unchecked, they don't uncheck (higher level nodes with no child nodes checked).

any hints on some approach to simulate the auto checking logic, setting check state to other than checked/unchecked, or?

3 Answers, 1 is accepted

Sort by
0
Yana
Telerik team
answered on 05 Feb 2010, 01:07 PM
Hi Steve,

You cannot use TriStateCheckBoxes and CheckChildNodes properties and at the same time prevent some nodes from checking.  I am not able to understand exactly the requirements, please send us simple page with the treeview and explain in more details the needed approach. You should open a support ticket in order to be able to attach files.

Kind regards,
Yana
the Telerik team

Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Follow the status of features or bugs in PITS and vote for them to affect their priority.
0
Steve
Top achievements
Rank 1
answered on 05 Feb 2010, 07:06 PM
ok, here is the complete markup for a test page I wrote to try to make tree work as desired.

it mostly works ok, but, when checking higher level nodes, they seem to like to go into a fully checked state, even though all the children are not checked, and I thought I could fix it if I was able to put my own logic in place to set the check state to indeterminate, but, there is no documented, or that I can find in the object methods anyway, set_checkState(), to line up with get_checkState().

the big difference from normal as far as requirements are:

at the lowest level on the tree, I'll call them 'Loss' nodes we have some rules as to what 'Losses' can be selected.

these rules are tied to something we call datapreparation types, datapreptype = 1 is normal 'Loss Analysis', and 2 is 'DGA', the page the tree is in can allow, one, the other, or both.

if the dataprep type is not contained in the datapreparation types, the Loss nodes are to be disabled.

then, the rules are as follows:

1. we never want loss nodes of type 'DGA' to be autoselected, selected by clicking a parent node, UNLESS we are in a page that only allows 'DGA' nodes.

2. we only allow for one NodeType of 'DGA' to be selected, so, selecting a DGA node, should unselect any other DGA node, actually, per rule 3, selecting a DGA node should unselect all other loss nodes.

3. We can either have one 'DGA' node selected, or, up to 5 loss analysis nodes, but no more.
which means if a 'Loss Analysis' node is selected, any DGA nodes should be unselected, and vice/versa.
We can allow the selection of more than 5 'Loss Analysis' nodes, we have IsValid logic to assure page cannot be submitted when more than 5 are selected, and show a message to that effect, so the tree doesn't need to not allow selection, or uncheck other nodes when too many 'Loss Analysis' nodes are checked.


when checkchildnodes is true, we had several problems with default behavior.

1.it checked child nodes even though they were disabled
2.we could not only check loss nodes (up to 5) of type 'Loss Analysis', and leave 'DGA' nodes unchecked.

when checkchildnodes is false, I could not find a way to make the parent nodes go to an indeterminate state when some child nodes were left unchecked when they were clicked.

I hope this makes some sense...

I know this is a lot of garbage to try to understand, and we would like to have changed the whole structure of displaying/selecting the data, but we're stuck with this hierarchy, if you will, from history, and business/users that are very adverse to change. so we gotta work within it if possible.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebTest._Default" %> 
 
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %> 
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
 
<html xmlns="http://www.w3.org/1999/xhtml" > 
<head runat="server">  
    <title>tree test page</title> 
 
<script src="jquery-1.4.1.js" type="text/javascript"></script> 
 
<script type="text/javascript">  
    function peDataPrepTypes() {  
        return $("#DataPreparationTypes").val();  
    }  
 
    function dataPrepTypesChanged() {  
        var prepTypes = peDataPrepTypes();  
        var treeView = $find("treeViewPortfolioData");  
        var nodes = treeView.get_allNodes();  
        for (var i = 0ii = nodes.length; i < ii; i++) {  
            var node = nodes[i];  
            var nodenodeType = node.get_attributes().getAttribute("NodeType");  
            if ("DGA" == nodeType) {  
                node.set_enabled(prepTypes.indexOf("2") > -1);  
            } else if ("Loss Analysis" == nodeType) {  
                node.set_enabled(prepTypes.indexOf("1") > -1);  
            }  
            node.uncheck();  
        }  
      
    }  
      
    function peTreeView_OnClientNodeChecking(sender, args) {  
 
        Sys.Debug.trace("peTreeView_OnClientNodeChecking - " + args.get_node().get_text());  
 
        var nodes = sender.get_allNodes();  
        for (var i = 0ii = nodes.length; i < ii; i++) {  
            var node = nodes[i];  
            node.get_attributes().setAttribute("PreCheckingChecked", node.get_checked());  
        }  
 
        var portfoliosChecked = 0;  
 
        var checkedNodes = sender.get_checkedNodes();  
        for (var i = 0ii = checkedNodes.length; i < ii; i++) {  
            var checkedNode = checkedNodes[i];  
            var nodeType = checkedNode.get_attributes().getAttribute("NodeType");  
            if (nodeType) {  
                if ("Portfolio" == nodeType) {  
                    portfoliosChecked++;  
                } else if ("DGA" == nodeType) {  
                    if ("DGA" == args.get_node().get_attributes().getAttribute("NodeType")) {  
                        if (checkedNode.get_checked() && (args.get_node() != checkedNode)) {  
                            checkedNode.uncheck();  
                        }  
                    }  
                }  
            }  
        }  
 
        return false;  
    }  
 
    function peTreeView_OnClientNodeChecked(sender, args) {  
 
        var sourceNode = args.get_node();  
        var sourceNodesourceNodeChecked = sourceNode.get_checked();  
        var sourceNodesourceNodeType = sourceNode.get_attributes().getAttribute("NodeType");  
 
        switch (sourceNodeType) {  
            case "Portfolio":  
                peSetChildNodesChecked(sender.get_allNodes(), sourceNode.get_nodes(), sourceNodeChecked);  
                break;  
            case "Peril":  
                if (sourceNodeChecked) {  
                    sourceNode.get_parent().set_checked(true);  
                } else if (!peAnyChildNodesChecked(sourceNode.get_parent().get_nodes())) {  
                    sourceNode.get_parent().set_checked(false);  
                }  
                peSetChildNodesChecked(sender.get_allNodes(), sourceNode.get_nodes(), sourceNodeChecked);  
                break;  
            case "Loss Analysis":  
            case "DGA":  
                if (sourceNodeChecked) {  
                    sourceNode.get_parent().set_checked(true);  
                    sourceNode.get_parent().get_parent().set_checked(true);  
                    peUncheckOtherLossTypeNodes(sender.get_allNodes(), sourceNodeType);  
                } else {  
                    if (!peAnyChildNodesChecked(sourceNode.get_parent().get_nodes())) {  
                        sourceNode.get_parent().set_checked(false);  
                        if (!peAnyChildNodesChecked(sourceNode.get_parent().get_parent().get_nodes())) {  
                            sourceNode.get_parent().get_parent().set_checked(false);  
                        }  
                    }  
                }  
                break;  
        }  
 
        var nodes = sender.get_allNodes();  
        for (var i = 0ii = nodes.length; i < ii; i++) {  
            var node = nodes[i];  
            if (("DGA" == node.get_attributes().getAttribute("NodeType")) &&  
                (node != sourceNode) &&   
                ("false" == node.get_attributes().getAttribute("PreCheckingChecked"))) {  
                Sys.Debug.trace("peTreeView_OnClientNodeChecked - unchecking : " + node.get_text());  
                node.uncheck();      
            }  
        }  
 
        if (sourceNode.get_checked()) {  
            //peExpandNode(node);  
        } else {  
            //peCollapseNode(sourceNode);  
        }  
        return false;  
 
        function peExpandNode(treeNode) {  
            var nodes = treeNode.get_nodes();  
            if (nodes.get_count() > 0) {  
                treeNode.expand();  
                for (var i = 0ii = nodes.get_count(); i < ii; i++) {  
                    expandNode(nodes.getNode(i));  
                }  
            }  
        }  
 
        function peCollapseNode(treeNode) {  
            var nodes = treeNode.get_nodes();  
            if (nodes.get_count() > 0) {  
                treeNode.collapse();  
                for (var i = 0ii = nodes.get_count(); i < ii; i++) {  
                    peCollapseNode(nodes.getNode(i));  
                }  
            }  
        }  
 
        function peSetChildNodesChecked(allNodes, childNodes, setChecked) {  
            for (var i = 0ii = childNodes.get_count(); i < ii; i++) {  
                var node = childNodes.getNode(i);  
                var nodenodeType = node.get_attributes().getAttribute("NodeType");  
                if (node.get_enabled()) {  
                    if ("DGA" == nodeType) {  
                        if (!setChecked) {  
                            node.set_checked(false);  
                        } else {  
                            if ("2" == peDataPrepTypes() && peNoDGANodesChecked(allNodes)) {  
                                node.set_checked(true);  
                                break;  
                            }  
                        }  
                    }  else if ("Loss Analysis" == nodeType) {  
                        if (!setChecked) {  
                            node.set_checked(false);  
                        } else {  
                            if (peNodesOfTypeChecked(allNodes, "Loss Analysis") < 5) {  
                                node.set_checked(true);  
                            }  
                        }  
                    } else {  
                        node.set_checked(setChecked);  
                        peSetChildNodesChecked(allNodes, node.get_nodes(), setChecked);  
                    }  
                }  
            }  
        }  
 
        function peUncheckOtherLossTypeNodes(nodes, lossNodeType) {  
            for (var i = 0ii = nodes.length; i < ii; i++) {  
                var node = nodes[i];  
                var nodenodeType = node.get_attributes().getAttribute("NodeType");  
                if ((("DGA" == nodeType) || ("Loss Analysis" == nodeType)) && (nodeType != lossNodeType)) {  
                    node.uncheck();  
                }  
            }  
        }  
 
        function peAnyChildNodesChecked(nodes) {  
            for (var i = 0ii = nodes.get_count(); i < ii; i++) {  
                if (nodes.getNode(i).get_checked()) return true;  
            }  
            return false;  
        }  
 
        function peNoDGANodesChecked(nodes) {  
            for (var i = 0ii = nodes.length; i < ii; i++) {  
                if (("DGA" == nodes[i].get_attributes().getAttribute("NodeType")) && nodes[i].get_checked()) return false;  
            }  
            return true;  
        }  
 
        function peNodesOfTypeChecked(nodes, nodeType) {  
            var checkedCount = 0;  
            for (var i = 0ii = nodes.length; i < ii; i++) {  
                var node = nodes[i];  
                if (node.get_checked() && (nodeType == node.get_attributes().getAttribute("NodeType"))) {  
                    checkedCount++;  
                }  
            }  
            return checkedCount;  
        }  
    }  
</script>      
</head> 
<body> 
    <form id="form1" runat="server">  
    <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager> 
    <telerik:RadAjaxManager ID="RadAjaxManager1" runat="server"></telerik:RadAjaxManager> 
    <div> 
        <input id="DataPreparationTypes" name="DataPreparationTypes" value="1,2" onchange="dataPrepTypesChanged();" /><br /> 
        <telerik:RadTreeView ID="treeViewPortfolioData"   
            CheckBoxes="true"   
            TriStateCheckBoxes="false"   
            CheckChildNodes="false"   
            ShowLineImages="false" 
            OnClientNodeChecking="peTreeView_OnClientNodeChecking" 
            OnClientNodeChecked="peTreeView_OnClientNodeChecked"   
            Skin="Vista" 
            runat="server">  
            <Nodes> 
                <telerik:RadTreeNode Text="2008-01-01" NodeType="Vintage" Expanded="true" Checkable="false">  
                    <Nodes> 
                        <telerik:RadTreeNode Text="EQ_US" NodeType="Portfolio" Expanded="true">  
                            <Nodes> 
                                <telerik:RadTreeNode Text="Earthquake" NodeType="Peril" Expanded="true">  
                                    <Nodes> 
                                        <telerik:RadTreeNode Text="LOSS 1" NodeType="Loss Analysis"></telerik:RadTreeNode> 
                                        <telerik:RadTreeNode Text="LOSS 2" NodeType="Loss Analysis"></telerik:RadTreeNode> 
                                        <telerik:RadTreeNode Text="LOSS 3" NodeType="Loss Analysis"></telerik:RadTreeNode> 
                                        <telerik:RadTreeNode Text="LOSS 4" NodeType="Loss Analysis"></telerik:RadTreeNode> 
                                        <telerik:RadTreeNode Text="DGA 1" NodeType="DGA"></telerik:RadTreeNode> 
                                        <telerik:RadTreeNode Text="DGA 2" NodeType="DGA"></telerik:RadTreeNode> 
                                    </Nodes> 
                                </telerik:RadTreeNode> 
                                <telerik:RadTreeNode Text="Hurricane" NodeType="Peril" Expanded="true">  
                                    <Nodes> 
                                        <telerik:RadTreeNode Text="LOSS 5" NodeType="Loss Analysis"></telerik:RadTreeNode> 
                                        <telerik:RadTreeNode Text="LOSS 6" NodeType="Loss Analysis"></telerik:RadTreeNode> 
                                        <telerik:RadTreeNode Text="LOSS 7" NodeType="Loss Analysis"></telerik:RadTreeNode> 
                                        <telerik:RadTreeNode Text="DGA 3" NodeType="DGA"></telerik:RadTreeNode> 
                                        <telerik:RadTreeNode Text="DGA 4" NodeType="DGA"></telerik:RadTreeNode> 
                                    </Nodes> 
                                </telerik:RadTreeNode> 
                                <telerik:RadTreeNode Text="Flood" NodeType="Peril" /> 
                            </Nodes> 
                        </telerik:RadTreeNode> 
                    </Nodes> 
                </telerik:RadTreeNode> 
            </Nodes> 
        </telerik:RadTreeView> 
    </div> 
    </form> 
</body> 
</html> 
 
0
Yana
Telerik team
answered on 11 Feb 2010, 07:53 AM
Hi Steve,

Thank you for the detailed explanation.

There's really no way to set the check state of the nodes as this is automatic process which depends on the other nodes. Why don't you set Checkable property to false for the nodes that you don't want to be checked, in this case they'll not be taken in TriStateCheckboxes hierarchy? Please let us know what you think about this.

All the best,
Yana
the Telerik team

Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Follow the status of features or bugs in PITS and vote for them to affect their priority.
Tags
TreeView
Asked by
Steve
Top achievements
Rank 1
Answers by
Yana
Telerik team
Steve
Top achievements
Rank 1
Share this question
or