PDA

View Full Version : Check Parent Tree Node if One of Child Node Is Checked



wonderway
31 May 2013, 12:58 AM
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? :(



{
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();
}
}
}

jasewell
31 May 2013, 9:37 AM
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:

p.set('checked', !!pChildCheckedCount);

wonderway
1 Jun 2013, 9:03 AM
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:

p.set('checked', !!pChildCheckedCount);

how to check siblings? can you give me full code? treepanel too complicated for me

jasewell
1 Jun 2013, 9:40 AM
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.

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.


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);
}

wonderway
2 Jun 2013, 7:02 PM
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.

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.


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 :D

here, the complete 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();
}

wonderway
3 Jun 2013, 11:18 PM
well, thanks jasewell! Actually, the best way is the simpliest way to do what i want :D

here, the complete 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:


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?

jasewell
4 Jun 2013, 6:19 AM
Well I don't know what your error is, but the following lines:

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.

wonderway
4 Jun 2013, 6:47 PM
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?

jasewell
5 Jun 2013, 6:54 AM
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.


if (p.parentNode) p.parentNode.set('checked', !!pChildCheckedCount);

wonderway
6 Jun 2013, 7:05 PM
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.


if (p.parentNode) p.parentNode.set('checked', !!pChildCheckedCount);


oh i see, thanks bro! :D