TreeNode.js - Fix in removeChild to reset this.childrenRendered = false if empty

  • In the 1.1.1 changelog, the following is listed:

    src/widgets/tree/TreeNode.js
    - Fix in removeChild to reset this.childrenRendered = false if empty

    Unfortunately this breaks my code that uses trees. Let me explain my scenario.


    Create a tree panel TP where the root isn't visible
    Create a root node RN
    TP.setRootNode(RN)
    TP.render()
    Create a new node (NN1) that has a child node (CN1)
    RN.appendChild(NN1)
    TP.expandAll()
    RN.removeChild(NN1)
    Create a new node (NN2) that has a child node (CN2)
    RN.appendChild(NN2)
    TP.expandAll()


    It is during the second expandAll call that the error occurs.

    TreePanel.expandAll calls this.root.expand(true).
    The root calls this.expandChildNodes(true).
    This method calls expand(true) on each of its children
    The expand method has the following check:

    if(!this.childrenRendered){
    this.renderChildren();
    }

    renderChildren in turn calls render on all of its children. When render is called for CN2 in the example above, it first calls render on its TreeNodeUI. The render method for the TreeNodeUI has the following:

    var targetNode = n.parentNode ? n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;

    n in this case is CN2, and since CN2 has a parentNode, it calls n.parentNode.ui.getContainer(). The return from this call is undefined. Later in the TreeNodeUI.render method, it calls this.renderElements(n, a, targetNode, bulkRender). renderElements in turn calls Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf.join("")). Since targetNode is undefined, an error.

    When I use v1.1, this whole error is avoided because this.childrenRendered is true thus this.renderChildren() doesn't get called.

    Please let me know if there is something wrong I am doing on my end or if you need additional information.

    Thanks!
    Steve


  • OK loeppky,

    try what Jack advises as we need to decide if this is really a bug or if it's a feature request.


  • The root cause is discussed in thread 66316 (http://extjs.com/forum/showthread.php?p=66316).


  • Have you tried appending the child node after the parent node has been appendedto the tree? This will prevent other issues as well, since the node will then be able to register itself with the tree (since it is part of the tree). e.g.

    root.appendChild(NN2);
    NN2.appendChild(CN2);
    tree.expandAll();


  • I just ran into this bug after upgrading to 1.1.1 as well. Worked great in 1.0 though.

    I am getting the same behavior and it is not fixed by the change you specified to
    removeChild() in TreeNode.js. This is probably becuase I am using asyncTreeNode and not TreeNode as my primary node type.

    I have a different use case though. I am using AsyncTreeNode for my nodes since the node may contain n levels of child nodes in the config

    note: parentNode may or may not be the root node in the method below.


    responseTree = new Ext.tree.TreePanel('ComposeEditorCenterRightBody_d iv', {
    animate:true,
    enableDD:true,
    loader: new Ext.tree.TreeLoader({
    uiProviders: {
    'PollResponseNodeUI' :PollResponseNodeUI
    }
    }),
    containerScroll: true,
    ddGroup: 'pollNodeResponseDD',
    lines:false,
    rootVisible:false
    });


    root = new Ext.tree.AsyncTreeNode({
    text: 'Root is hidden',
    draggable:false,
    id:"treeRoot",
    allowDrop:true,
    children: ,
    type:"root"
    });

    responseTree.setRootNode(root);
    responseTree.render();


    // later I call createTreeNode and pass in the root or any node with a new config.

    createTreeNode : function (parentNode,dataConfig){
    var newTreeNode = new Ext.tree.AsyncTreeNode(dataConfig);
    var addedNode = parentNode.appendChild(newTreeNode);
    parentNode.expand();
    addedNode.expand();
    addedNode.select();
    }



    The tree loads correctly the first time. But after the children of a node are removed, any children added to that node are no longer visible.


  • Can you please upload a code sample that drops into the tree examples folder and exhibits the issue. Thanks.


  • Thanks for providng a test case. That made it so much easier. It has been fixed in SVN.

    The fix is rather simple. This code goes in removeChild on TreeNode:

    if(!this.firstChild && !this.isHiddenRoot()) {
    this.childrenRendered = false;
    }


  • Saki,

    I'm sorry for the delayed response. I had a really hectic day yesterday. I tried what Jack suggested, and it still doesn't work. Here is the sequence of events:

    Create a tree panel TP where the root isn't visible

    Create a root node RN
    TP.setRootNode(RN)
    TP.render()
    Create a new node (NN1)
    RN.appendChild(NN1)
    TP.expandAll()
    RN.removeChild(NN1)
    Create a new node (NN2)
    RN.appendChild(NN2)
    TP.expandAll()


    As discussed in the other post, the issue is when the root node has been rendered, but its childrenRendered property gets set to false. From that point forward, no additional nodes can be appended.

    Thanks for your time and help!
    Steve


  • You bet. I will work on getting a code sample out today. If not, I'll have it done for tomorrow.


  • This has been added to the list. Thanks.


  • Saki,

    Thanks a lot! Let me know if any additional explanation is needed.

    Steve


  • Hi Jack,

    Here is a sample that can be dropped in examples/tree to demonstrate the Tree.appendChild bug in 1.1.1. Let me know if you need anything else!

    Steve


  • I've notified Jack about this bug.


  • Hi Jack,

    Thanks for taking time to reply. I am sorry for the delayed response. I will subscribe to the tread so I will know to respond faster.

    I haven't tried appending the child node after the parent node has been appended to the tree. In my application's case, the "unit" that a user interacts with is a node which can have 0 or more children nodes, which can also have 0 or children nodes (a tree of depth 2). Most of the time a user is browsing a bunch of these "units". The user though also has the ability to edit one of the "units" in a dialog window. What's most intuitive at a code level is for is to append whole "unit" to the invisible root node of the edit dialog window, not adding one child at a time of the "unit" to the edit dialog window's root node.

    Also, just to make sure you were aware of it, I discussed the root issue in thread 66316: http://extjs.com/forum/showthread.php?p=66316. It may make sense to move the discussion over to that thread as it is a little more clear about the specific problem. Either way.

    Thanks again for your help!
    Steve







  • #If you have any other info about this subject , Please add it free.#
    Your name:
    E-mail:
    Telphone:

    Your comments:


    If you have any other info about TreeNode.js - Fix in removeChild to reset this.childrenRendered = false if empty , Please add it free.