How to delete a node from an Ext TreePanel if the node hasn't been rendered

Juan Mendes picture Juan Mendes · Jan 31, 2011 · Viewed 11.8k times · Source

I've found that I can't delete nodes that haven't been rendered yet. The following code shows what I mean. I ran it from the Chrome's (and Firebug's) command line while on http://dev.sencha.com/deploy/dev/exa...dow/hello.html (since that page has ext preloaded)

I typed each statement separately to make sure there were no issues with asynchronous operations (even though the tree data is in memory)

Ext.getBody.update('');
// Tree with preloaded nodes in memory 
var tree = new Ext.tree.TreePanel({ 
   renderTo: Ext.getBody(),  
   width: 300,  
   height: 500,  
   rootVisible: false, 
   loader: new Ext.tree.TreeLoader({preloadChildren:true}), 
   root: new Ext.tree.AsyncTreeNode({ 
     expandend: true, 
     children: [ 
        {text: 'Folder 1', id: 'folder1', leaf: false, children: [ 
            {text: 'File 1', id: 'file1', leaf: true}, 
            {text: 'File 2', id: 'file2', leaf: true} 
        ]} 
     ] 
   }) 
}); 

// Try to delete 'File 1', notice that the folder has never been expanded 
tree.getRootNode().childNodes[0].childNodes[0].remove(true); 

// Expand the node and see that 'File 1' is still there 
tree.getRootNode().childNodes[0].expand(); 

// Delete the first child 1 again, it works now that it's been rendered 
tree.getRootNode().childNodes[0].childNodes[0].remove(true);

Any suggestions on what to do?

ANSWER

var nodeToRemove = tree.getRootNode().childNodes[0].childNodes[0];
if (!nodeToRemove.rendered) {
    var children = node.parentNode.attributes.children;
    Ext.each(children, function(child, index){
        if (child.id == nodeToRemove.id) {
            chilren.splice(index, 1);
            return false;
        }
    }) ;
} else {
    nodeToRemove.remove(true);
}

Answer

user123444555621 picture user123444555621 · Feb 1, 2011

Ext.tree.TreePanel is the one component I hate most (followed by FormPanel).

Here is what happens: The TreeLoader preloads the root node's child nodes from its original config object, and so does a call to AsyncTreeNode.expand, which will basically reset the tree.

So, you're gonna have to remove the node from your rootNode's config like this before expanding:

tree.getRootNode().attributes.children[0].children.shift();

Edit: Actually, this is more intuitive:

tree.getRootNode().childNodes[0].attributes.children.shift();

(does the same thing, since root.childNodes[0].attributes === root.attributes.children[0])