-
1 Dec 2008 5:31 AM #41Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 44
Are you sure your node ids are unique?
-
1 Dec 2008 5:35 AM #42
Yes, the id is an autoincremented primary key. I use "category_", "customer_" and "premises_" as a prefix.
-
1 Dec 2008 6:03 AM #43Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 44
I can't reproduce your problem...
Is there a way you can make your example available on the internet?
-
1 Dec 2008 7:03 AM #44
As I wrote some example code I found out what's causing the error.
I've removed the categories checkbox because I don't want the user to be able to select to many premises at once.
So, on the top parents (categories) I'm not using the checked -option.
Is there another way to remove the checkboxes on the top level nodes (categories)?
...here's the example code showing the problem:
example.html (my changes marked in bold)
heatTree.phpCode:<script type="text/javascript"> Ext.onReady(function(){ var heatDs = new Ext.tree.TreeLoader({ url: 'heatTree.php', //preloadChildren:true, baseAttrs:{ uiProvider: Ext.tree.TriStateNodeUI }, listeners: { beforeload: function(store, node, callback) { this.baseParams.depth = node.getDepth(); } } }); var root = new Ext.tree.TreeNode({ //children:data id: '0' }); new Ext.tree.TreeLoader({ preloadChildren:true, baseAttrs:{ uiProvider:Ext.tree.TriStateNodeUI } }).load(root); new Ext.Viewport({ layout:'fit', items:[{ xtype:'treepanel', title:'Tree checkbox test', rootVisible:false, autoScroll:true, root:root }] }); heatDs.load(root) }); </script>
PHP Code:<?php
$depth = $_POST['depth'];
$node = substr($_POST['node'], 9);
switch($depth) {
case 0:
// Init tree, return categories
$nodes[0]['id'] = 'category_1';
$nodes[0]['text'] = 'Category 1';
//$nodes[0]['checked'] = false; // Remove comment to make it work as supposed
$nodes[0]['expanded'] = false;
$nodes[1]['id'] = 'category_2';
$nodes[1]['text'] = 'Category 2';
//$nodes[1]['checked'] = false; // Remove comment to make it work as supposed
$nodes[1]['expanded'] = false;
break;
case 1:
// A category have been chosen, return that categorys customers
if($node == 1) {
$nodes[0]['id'] = 'customer_1';
$nodes[0]['text'] = 'Customer 1';
$nodes[0]['checked'] = false;
$nodes[0]['expanded'] = false;
$nodes[1]['id'] = 'customer_2';
$nodes[1]['text'] = 'Customer 2';
$nodes[1]['checked'] = false;
$nodes[1]['expanded'] = false;
}
if($node == 2) {
$nodes[0]['id'] = 'customer_3';
$nodes[0]['text'] = 'Customer 3';
$nodes[0]['checked'] = false;
$nodes[0]['expanded'] = false;
$nodes[1]['id'] = 'customer_4';
$nodes[1]['text'] = 'Customer 4';
$nodes[1]['checked'] = false;
$nodes[1]['expanded'] = false;
}
break;
case 2:
// A customer have benn chosen, return that customers premises
if($node == 1) {
$nodes[0]['id'] = 'premises_1';
$nodes[0]['text'] = 'Premises 1';
$nodes[0]['checked'] = false;
$nodes[0]['leaf'] = true;
$nodes[1]['id'] = 'premises_2';
$nodes[1]['text'] = 'Premises 2';
$nodes[1]['checked'] = false;
$nodes[1]['leaf'] = true;
}
if($node == 2) {
$nodes[0]['id'] = 'premises_3';
$nodes[0]['text'] = 'Premises 3';
$nodes[0]['checked'] = false;
$nodes[0]['leaf'] = true;
$nodes[1]['id'] = 'premises_4';
$nodes[1]['text'] = 'Premises 4';
$nodes[1]['checked'] = false;
$nodes[1]['leaf'] = true;
}
if($node == 3) {
$nodes[0]['id'] = 'premises_5';
$nodes[0]['text'] = 'Premises 5';
$nodes[0]['checked'] = false;
$nodes[0]['leaf'] = true;
$nodes[1]['id'] = 'premises_6';
$nodes[1]['text'] = 'Premises 6';
$nodes[1]['checked'] = false;
$nodes[1]['leaf'] = true;
}
if($node == 4) {
$nodes[0]['id'] = 'premises_7';
$nodes[0]['text'] = 'Premises 7';
$nodes[0]['checked'] = false;
$nodes[0]['leaf'] = true;
$nodes[1]['id'] = 'premises_8';
$nodes[1]['text'] = 'Premises 8';
$nodes[1]['checked'] = false;
$nodes[1]['leaf'] = true;
}
}
$data = json_encode($nodes);
echo $data;
?>
-
1 Dec 2008 8:22 AM #45Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 44
Yes, that's a really big bug you found.
You can fix it with:
Code:Ext.override(Ext.tree.TriStateNodeUI, { onCheckChange :function(){ Ext.tree.TriStateNodeUI.superclass.onCheckChange.apply(this, arguments); var p = this.node; while((p = p.parentNode) && p.getUI().updateParent && p.getUI().checkbox && !p.getUI().isUpdating) { p.getUI().updateParent(); } } });
-
2 Dec 2008 1:13 AM #46
Yes, it worked like a charm
.
Another issue:
When I'm loading children on-the-fly from the server, as I do (using preloadChildren: false), I want the children to be loaded and checked (without expanding the parent) when checking an unexpanded parent.
1. The categories is loaded.
2. I expand Category 1 (Customer 1 and Customer 2 becomes visible).
3. I check Customer 1 (without expanding it first).
4. I alert getChecked(). This should also alert the childrens of Customer 1...
Another question:
What is the best way to send checked boxes to the server?
I want to load a google chart image depending on what nodes is checked. When I'm clicking a parent node, checkchange will be fired multiple times. I need a listener that is being fired only once, when all children is checked/unchecked...
This ugly code is what I've come up with for the moment (resumeEvents() isn't doing what it should though...):
Code:{ xtype:'treepanel', title:'Tree checkbox test', rootVisible:false, autoScroll:true, root:root, listeners: { checkchange: function(node, isChecked) { var isParent = !node.isLeaf(); var checkedNodes = []; if(isParent && isChecked) { this.suspendEvents(); node.expand(true, true, function(node) { node.cascade(function() { if(!this.getUI().isChecked()) this.getUI().toggleCheck(true); if(this.isLeaf()) checkedNodes.push(this.id); }); alert(checkedNodes); }); } else this.resumeEvents(); } } }
-
2 Dec 2008 2:20 AM #47Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 44
I think what you actually need is a way to set the check state of loaded children based on the checked state of the parent.
Try:
(and your server should not return a checked attribute for premises)Code:loader: new Ext.tree.Loader({ url: '...', baseAttrs: { uiProvider:Ext.tree.TriStateNodeUI }, listeners: { beforeload: function(loader, node, callback) { if(node.attributes.checked !== undefined){ loader.baseAttrs.checked = node.attributes.checked; } else { delete loader.baseAttrs.checked; } } } }
-
2 Dec 2008 2:49 AM #48
Yes, it renders the children checked when expanding the parent (customer). But it will not include the unrendered children (premises) using getChecked().
Somehow I must load the children when checking the parent (without expanding the parent), else the tree wont know anything about the children...
(And, if I somehow can have some sort of a callback function or listener when all the children is finished being checked/unchecked, that would be heaven)
-
2 Dec 2008 4:15 AM #49
Ok, I made the following changes, workes fine for my needs. It will store all checked leafs in an array (checkedLeafs). When a checkbox is clicked it will add leafs to the array and finally fire leafschange.
In other words: Checking a parent will expand the childrens, make them checked, adding them to the array and finally fire leafschange once.
Please, tell me if you have a better way doing this.
Code:{ xtype:'treepanel', title:'Tree checkbox test', rootVisible:false, autoScroll:true, root:root, checkedLeafs:[], listeners: { leafschange: function() { alert(this.checkedLeafs); } } }Code:Ext.override(Ext.tree.TreeNodeUI, { onCheckboxClick:function() { // My code var isChecked = this.node.attributes.checked == null ? false : !this.node.attributes.checked; var isParent = !this.node.isLeaf(); if(isParent) { if(isChecked && !this.node.isExpanded()) { this.node.expand(true, true, function(node) { node.cascade(function() { if(!this.getUI().isChecked()) this.getUI().toggleCheck(true); if(this.isLeaf() && this.ownerTree.checkedLeafs.indexOf(this) < 0) this.ownerTree.checkedLeafs.push(this); }); node.ownerTree.fireEvent('leafschange', this); }); } else { var i = 0; this.node.cascade(function(node) { if(node.isLeaf()) { if(isChecked) this.node.ownerTree.checkedLeafs.push(node); else this.node.ownerTree.checkedLeafs.remove(node) } if(i == this.node.childNodes.length) this.node.ownerTree.fireEvent('leafschange'); i++; }, this); } } else { isChecked ? this.node.ownerTree.checkedLeafs.push(this.node) : this.node.ownerTree.checkedLeafs.remove(this.node); this.node.ownerTree.fireEvent('leafschange'); } // End of my code if(!this.disabled){ this.toggleCheck(); } } });
-
2 Dec 2008 4:36 AM #50Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 44


Reply With Quote