PDA

View Full Version : [CLOSED] Tree/Node expand recursively broken



Ronaldo
26 May 2014, 1:07 PM
Hi,

I'm trying to expand a tree's rootnode recursively.
First, I tried the TreePanel's but it gives an error:

Then I tried to use the RootNode's.expand method:

rootNode.expand(true, callbackFn, scope);
but the callbackFn is called directly when the first level of nodes are loaded. My tree has more nested nodes that are not loaded.

Looking in the code of the NodeInterface, I found the reason:


expandChildren: function(recursive, callback, scope, /* private */ singleExpand) {

<zip>


for (i = 0; i < ln; ++i) {
node = allNodes[i];
if (!node.isLeaf()) {
expandNodes[expandNodes.length] = node;
}
}
ln = expandNodes.length;


for (i = 0; i < ln; ++i) {
expandNodes[i].expand(recursive);
// Should be: expand(recursive, callback, scope)
}

// And directly, the callback is called, even if more childNodes need to be loaded
if (callback) {
Ext.callback(callback, scope || me, [me.childNodes]);
}

// I tried:
// if(!ln && callback) {
// Ext.callback(callback, scope || me, [me.childNodes]);
// }
// But that calls the callback for every node that has its childnodes loaded.
}


Looking through the code, I didn't find an easy way to fix it. Of course, loading nested trees is a more advanced asynchronously topic, but would it not be a great plus if ExtJs would provide natively some of the higher level functionality like async (https://github.com/caolan/async)?

Recursively loading the tree is something along these lines using an async.queue:


var list = [],
allNodesLoadedFn = function() {
console.log("The END");
},
nodeLoadedFn = function(node) {
console.log("Loaded node "+node.get("Name"));
},
taskFn = function(node, callback) {
// Mark the node as being loaded
list.push(node);
node.expand(false, function(childNodes) {
// Node is loaded/expanded now
Ext.Array.remove(list, node);

// This calls the taskCompletedFn where optional childnodes
// are added as separate tasks
for(var i=0;i<childNodes.length;i++) {
queue.push(childNodes[i], nodeLoadedFn);
}

// Inform async queue we're done for this node
callback(node);

// Unfortunately the async.queue doesn't have a callback when
// the queue is empty. Use this list as a backup. If it's empty, we're ready.
if(list.length==0) {
allNodesLoadedFn();
}
});
},
queue = async.queue(taskFn, 3);


queue.push(rootNode, nodeLoadedFn);



Which might be totally unreadable for some, but it works. And you can even set the number of nodes loading/expanding at the same time by changing the '3' in the line.


queue = async.queue(taskFn, 3);

PS: Keep up the good work. Loving it.

mitchellsimoens
27 May 2014, 6:19 AM
Thanks for the report! I have opened a bug in our bug tracker.

gridswift
17 Nov 2014, 8:19 PM
Many thanks for this workaround - beautiful.

harrypottar
17 Sep 2015, 8:02 AM
can some one post the workaround, I'm still seeing this in 5.1.1