Results 1 to 10 of 10

Thread: Check Parent Tree Node if One of Child Node Is Checked

  1. #1
    Sencha User
    Join Date
    May 2013
    Posts
    24

    Default Answered: Check Parent Tree Node if One of Child Node Is Checked

    I have Checked Tree like this:

    ParentNode
    |_SubParentNode
    -ChildNode1
    -ChildNode2

    Question:
    1. I want to checked & unchecked all ChildNode if i check & uncheck ParentNode or SubParentNode
    2. I want to checked ParentNode & SubParentNode if i check one of ChildNode

    I tried this code, for Q1 it works, but for Q2 if i check one of ChildNode (ChildNode1), ParentNode & SubParentNode is check, however if check ChildNode2 and uncheck ChildNode1, ParentNode & SubParentNode is uncheck, how to fix this?

    Code:
    {
        xtype: 'treepanel',
        id: 'checkTree',
            rootVisible: false,
        useArrows: true,
        store: TableTreeStore,
        renderTo: Ext.getBody(),
        listeners: 
        {
             checkchange: function(node, checked, eOpts){
                node.eachChild(function(n) {
                    node.cascadeBy(function(n){
                        n.set('checked', checked);}
                     );
                });
    
    
                p = node.parentNode;
                p.suspendEvents();
                p.parentNode.set('checked', checked);
                p.set('checked', checked);
                p.resumeEvents();
            }
        }
    }

  2. Short answer: you know how to get to the parent of a node, and you know how to loop across the children of a node. Checking the siblings is as simple as setting a variable to 0 and incrementing it every time you find a child that's checked.
    Code:
    var pChildCheckedCount = 0;
    p.eachChild(function(c) { if (c.get('checked')) pChildCheckedCount++; });
    Long answer: You basically want every single non-leaf node in your tree to be checked iff it has at least one child that is checked, yeah? So rather than starting at the node where the check operation happened, why not start at the root and just do that.

    Code:
    checkchange: function(node) {
        var rootNode = node.getOwnerTree().getRootNode(),
            cascadeCheck = function(n) {
                if (!n.isLeaf()) { // Leaf nodes are checked/unchecked only by the user.
                    n.suspendEvents();
                    n.set('checked', false);
                    var childCheckCount = 0;
                    n.cascadeBy(function(c) {
                        cascadeCheck(c);
                        if (c.get('checked')) childCheckCount++;
                    });
                    n.set('checked', !!childCheckCount);
                    n.resumeEvents();
                }
            };
        
        rootNode.eachChild(cascadeCheck);
    }

  3. #2
    Sencha User
    Join Date
    Feb 2013
    Location
    Lawrence, KS, USA
    Posts
    28
    Answers
    2

    Default

    It sounds like you need to check siblings before setting your parent node. You could step through p's children and add up how many of them are checked, then:
    Code:
    p.set('checked', !!pChildCheckedCount);

  4. #3
    Sencha User
    Join Date
    May 2013
    Posts
    24

    Default

    Quote Originally Posted by jasewell View Post
    It sounds like you need to check siblings before setting your parent node. You could step through p's children and add up how many of them are checked, then:
    Code:
    p.set('checked', !!pChildCheckedCount);
    how to check siblings? can you give me full code? treepanel too complicated for me

  5. #4
    Sencha User
    Join Date
    Feb 2013
    Location
    Lawrence, KS, USA
    Posts
    28
    Answers
    2

    Default

    Short answer: you know how to get to the parent of a node, and you know how to loop across the children of a node. Checking the siblings is as simple as setting a variable to 0 and incrementing it every time you find a child that's checked.
    Code:
    var pChildCheckedCount = 0;
    p.eachChild(function(c) { if (c.get('checked')) pChildCheckedCount++; });
    Long answer: You basically want every single non-leaf node in your tree to be checked iff it has at least one child that is checked, yeah? So rather than starting at the node where the check operation happened, why not start at the root and just do that.

    Code:
    checkchange: function(node) {
        var rootNode = node.getOwnerTree().getRootNode(),
            cascadeCheck = function(n) {
                if (!n.isLeaf()) { // Leaf nodes are checked/unchecked only by the user.
                    n.suspendEvents();
                    n.set('checked', false);
                    var childCheckCount = 0;
                    n.cascadeBy(function(c) {
                        cascadeCheck(c);
                        if (c.get('checked')) childCheckCount++;
                    });
                    n.set('checked', !!childCheckCount);
                    n.resumeEvents();
                }
            };
        
        rootNode.eachChild(cascadeCheck);
    }

  6. #5
    Sencha User
    Join Date
    May 2013
    Posts
    24

    Default

    Quote Originally Posted by jasewell View Post
    Short answer: you know how to get to the parent of a node, and you know how to loop across the children of a node. Checking the siblings is as simple as setting a variable to 0 and incrementing it every time you find a child that's checked.
    Code:
    var pChildCheckedCount = 0;
    p.eachChild(function(c) { if (c.get('checked')) pChildCheckedCount++; });
    Long answer: You basically want every single non-leaf node in your tree to be checked iff it has at least one child that is checked, yeah? So rather than starting at the node where the check operation happened, why not start at the root and just do that.

    Code:
    checkchange: function(node) {
        var rootNode = node.getOwnerTree().getRootNode(),
            cascadeCheck = function(n) {
                if (!n.isLeaf()) { // Leaf nodes are checked/unchecked only by the user.
                    n.suspendEvents();
                    n.set('checked', false);
                    var childCheckCount = 0;
                    n.cascadeBy(function(c) {
                        cascadeCheck(c);
                        if (c.get('checked')) childCheckCount++;
                    });
                    n.set('checked', !!childCheckCount);
                    n.resumeEvents();
                }
            };
        
        rootNode.eachChild(cascadeCheck);
    }
    well, thanks jasewell! Actually, the best way is the simpliest way to do what i want

    here, the complete code:
    Code:
    checkchange: function(node, checked, eOpts){
        node.eachChild(function(n) {
            node.cascadeBy(function(n){
                n.set('checked', checked);
            });
        });
    
    
        //check parent node if child node is check
        p = node.parentNode;
        var pChildCheckedCount = 0;
        p.suspendEvents();
        p.eachChild(function(c) { 
            if (c.get('checked')) pChildCheckedCount++; 
                p.parentNode.set('checked', !!pChildCheckedCount);
                p.set('checked', !!pChildCheckedCount);
            });
        p.resumeEvents();
    }

  7. #6
    Sencha User
    Join Date
    May 2013
    Posts
    24

    Default

    Quote Originally Posted by wonderway View Post
    well, thanks jasewell! Actually, the best way is the simpliest way to do what i want

    here, the complete code:
    Code:
    checkchange: function(node, checked, eOpts){
        node.eachChild(function(n) {
            node.cascadeBy(function(n){
                n.set('checked', checked);
            });
        });
    
    
        //check parent node if child node is check
        p = node.parentNode;
        var pChildCheckedCount = 0;
        p.suspendEvents();
        p.eachChild(function(c) { 
            if (c.get('checked')) pChildCheckedCount++; 
                p.parentNode.set('checked', !!pChildCheckedCount);
                p.set('checked', !!pChildCheckedCount);
            });
        p.resumeEvents();
    }
    jasewell, sorry to bother you again, seems this code give error:
    Code:
    p.parentNode.set('checked', !!pChildCheckedCount);
    
    How to fix this? if i delete those code, i just can check subparent node, parent node is not checked, how to checked subparent node & parent node?

  8. #7
    Sencha User
    Join Date
    Feb 2013
    Location
    Lawrence, KS, USA
    Posts
    28
    Answers
    2

    Default

    Well I don't know what your error is, but the following lines:
    Code:
    p.parentNode.set('checked', !!pChildCheckedCount);
    p.set('checked', !!pChildCheckedCount);
    have no business being in the eachChild() block. They should be right before the resumeEvents() call.

  9. #8
    Sencha User
    Join Date
    May 2013
    Posts
    24

    Default

    here's my error when i click ParentNode:

    Uncaught TypeError: Cannot call method 'set' of null
    maybe because i calling p.parentNode (node.parentNode.parentNode) is not right. Any suggestion?

  10. #9
    Sencha User
    Join Date
    Feb 2013
    Location
    Lawrence, KS, USA
    Posts
    28
    Answers
    2

    Default

    Quote Originally Posted by wonderway View Post
    here's my error when i click ParentNode:



    maybe because i calling p.parentNode (node.parentNode.parentNode) is not right. Any suggestion?
    Depending on where you start the process, you may not be able to count on having as many levels of inheritance as you expect. In other words, you should check to see if p.parentNode is truthy before trying to do anything to it.
    Code:
    if (p.parentNode) p.parentNode.set('checked', !!pChildCheckedCount);

  11. #10
    Sencha User
    Join Date
    May 2013
    Posts
    24

    Default

    Quote Originally Posted by jasewell View Post
    Depending on where you start the process, you may not be able to count on having as many levels of inheritance as you expect. In other words, you should check to see if p.parentNode is truthy before trying to do anything to it.
    Code:
    if (p.parentNode) p.parentNode.set('checked', !!pChildCheckedCount);
    oh i see, thanks bro!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •