The docs for tree.remove () say:
However, when I call tree.remove (), the treeNode is deleted, but it seems to me that its children are not.
Note that the treeNode and its children are removed from the UI, but not from the Tree memory.
I have to explicitly delete all children records recursively for them to be actually deleted.
Versions
GWT 2.3.0
SmartGWT 3.0p-2012-04-26
SmartGWT 3.0p-2012-08-31 (latest)
Dev console: SmartClient Version: v8.2p_2012-08-31/LGPL Development Only (built 2012-08-31)
FireFox 6.0
Steps to reproduce
1. Create and configure a TreeGrid + Tree
2. Load the tree with at least 1 root and 1 child
3. Call tree.remove () to remove the root
4. Load the tree with the same root and child as #2, and you get this exception:
And this in the dev console:
With the code sample below, you can reproduce the not-working case by clicking:
1. Load
2. Dump Tree, to verify that the parent/child have been added
3. Remove Root A, to let tree.remove (TreeNode) remove a node
4. Dump Tree, to verify that the tree claims that the records are deleted
5. Load, to get the failure above
If I replace tree.remove () with tree.removeTreeNodeExceptForRootTreeNode (), then it seems to work:
With the code sample below, you can reproduce the working case by clicking:
1. Load
2. Dump Tree, to verify that the parent/child have been added
3. Remove Root A Explicit, to delete all children manually
4. Dump Tree, to verify that the tree claims that the records are deleted
5. Load, to verify that the tree seems properly built again, and without errors
Code to reproduce:
Any advice appreciated...
Code:
Removes a node, along with all its children.
Note that the treeNode and its children are removed from the UI, but not from the Tree memory.
I have to explicitly delete all children records recursively for them to be actually deleted.
Versions
GWT 2.3.0
SmartGWT 3.0p-2012-04-26
SmartGWT 3.0p-2012-08-31 (latest)
Dev console: SmartClient Version: v8.2p_2012-08-31/LGPL Development Only (built 2012-08-31)
FireFox 6.0
Steps to reproduce
1. Create and configure a TreeGrid + Tree
2. Load the tree with at least 1 root and 1 child
3. Call tree.remove () to remove the root
4. Load the tree with the same root and child as #2, and you get this exception:
Code:
00:00:56.388 [ERROR] 13:11:10.404:MUP6:WARN:Tree:isc_Tree_0:Adding node to tree with id property set to:3. A node with this ID is already present in this Tree - th at node will be replaced. Note th at this warning may be disabled by setting the reportCollisions attribute to false.com.smartgwt.client.core.JsObject$SGWT_WARN: 13:11:10.404:MUP6:WARN:Tree:isc_Tree_0:Adding node to tree with id property set to:3. A node with this ID is already present in this Tree - th at node will be replaced. Note th at this warning may be disabled by setting the reportCollisions attribute to false. at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:105) at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71) at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:167) at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:326) at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:207) at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:132) at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561) at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269) at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91) at com.smartgwt.client.widgets.tree.Tree.add(Tree.java) at TestTreeRemove$1.onClick(TestTreeRemove.java:77)
Code:
13:20:13.809:INFO:Log:initialized 13:20:13.819:WARN:Log:NOTE: Firebug is enabled. Firebug greatly slows the performance of applications that make heavy use of JavaScript. Isomorphic highly recommends Firebug for troubleshooting, but Firebug and other development tools should be disabled when assessing the real-world performance of SmartClient applications. 13:20:14.457:WARN:Log:New Class ID: 'EditPane' collides with ID of existing Class object '[DataSource ID:EditPane]'. Existing object will be replaced. This conflict would be avoided by disabling ISC Simple Names mode. See documentation for further information. 13:20:19.570:INFO:Log:isc.Page is loaded 13:20:32.749:MUP7:WARN:Tree:isc_Tree_0:Adding node to tree with id property set to:3. A node with this ID is already present in this Tree - that node will be replaced. Note that this warning may be disabled by setting the reportCollisions attribute to false. 13:20:32.752:MUP7:WARN:Tree:isc_Tree_0:Adding node to tree with id property set to:4. A node with this ID is already present in this Tree - that node will be replaced. Note that this warning may be disabled by setting the reportCollisions attribute to false.
1. Load
2. Dump Tree, to verify that the parent/child have been added
3. Remove Root A, to let tree.remove (TreeNode) remove a node
4. Dump Tree, to verify that the tree claims that the records are deleted
5. Load, to get the failure above
If I replace tree.remove () with tree.removeTreeNodeExceptForRootTreeNode (), then it seems to work:
Code:
/** * Removes the given TreeNode and all its children * @param tree * @param treeNode */ private void removeTreeNodeExceptForRootTreeNode ( final Tree tree, final TreeNode treeNode) { // remove children first final TreeNode[] childTreeNodeArray = tree.getChildren (treeNode); if (childTreeNodeArray != null) { for (final TreeNode childTreeNode : childTreeNodeArray) { removeTreeNodeExceptForRootTreeNode (tree, childTreeNode); } } // finally remove this node, unless it is the root if (treeNode.getAttributeAsInt (tree.getIdField ()) != 1) { tree.remove (treeNode); } else { GWT.log ("removeTreeNodeRecursive (): not deleting rootTreeNode"); } }
1. Load
2. Dump Tree, to verify that the parent/child have been added
3. Remove Root A Explicit, to delete all children manually
4. Dump Tree, to verify that the tree claims that the records are deleted
5. Load, to verify that the tree seems properly built again, and without errors
Code:
13:18:23.081:INFO:Log:initialized 13:18:23.090:WARN:Log:NOTE: Firebug is enabled. Firebug greatly slows the performance of applications that make heavy use of JavaScript. Isomorphic highly recommends Firebug for troubleshooting, but Firebug and other development tools should be disabled when assessing the real-world performance of SmartClient applications. 13:18:23.738:WARN:Log:New Class ID: 'EditPane' collides with ID of existing Class object '[DataSource ID:EditPane]'. Existing object will be replaced. This conflict would be avoided by disabling ISC Simple Names mode. See documentation for further information. 13:18:28.408:INFO:Log:isc.Page is loaded
Code:
import com.smartgwt.client.widgets.tree.TreeGrid; import com.smartgwt.client.widgets.tree.Tree; import com.smartgwt.client.widgets.tree.TreeGridField; import com.smartgwt.client.widgets.tree.TreeNode; import com.smartgwt.client.widgets.layout.VLayout; import com.smartgwt.client.widgets.events.ClickHandler; import com.smartgwt.client.widgets.events.ClickEvent; import com.smartgwt.client.widgets.IButton; import com.smartgwt.client.types.SortDirection; import com.smartgwt.client.types.TreeModelType; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; public class TestTreeRemove implements EntryPoint { /** * The EntryPoint interface */ public void onModuleLoad () { // configure Tree final Tree tree = new Tree (); tree.setModelType (TreeModelType.PARENT); tree.setNameProperty ("name"); tree.setIdField ("nodeId"); tree.setParentIdField ("parentNodeId"); tree.setShowRoot (true); // configure root TreeNode final TreeNode rootTreeNode = new TreeNode ("root"); rootTreeNode.setAttribute (tree.getIdField (), 1); tree.setRoot (rootTreeNode); // configure TreeGrid final TreeGridField nameField = new TreeGridField ("name", "Name", 200); final TreeGrid treeGrid = new TreeGrid (); treeGrid.setWidth (300); treeGrid.setHeight (200); treeGrid.setSortFoldersBeforeLeaves (true); treeGrid.setSortDirection (SortDirection.ASCENDING); treeGrid.setFields (nameField); treeGrid.setData (tree); // Root A // Root A - Child A // Root A - Child B final TreeNode rootATreeNode = new TreeNode (); final IButton loadButton = new IButton (); loadButton.setTitle ("Load"); loadButton.addClickHandler (new ClickHandler () { public void onClick (final ClickEvent event) { rootATreeNode.setAttribute (tree.getIdField (), 2); rootATreeNode.setAttribute (tree.getParentIdField (), 1); rootATreeNode.setAttribute ("name", "Root A"); tree.add (rootATreeNode, rootTreeNode); final TreeNode childA = new TreeNode (); childA.setAttribute (tree.getIdField (), 3); childA.setAttribute (tree.getParentIdField (), 2); childA.setAttribute ("name", "Root A - Child A"); tree.add (childA, rootATreeNode); final TreeNode childB = new TreeNode (); childB.setAttribute (tree.getIdField (), 4); childB.setAttribute (tree.getParentIdField (), 2); childB.setAttribute ("name", "Root A - Child B"); tree.add (childB, rootATreeNode); } }); // button to delete the root final IButton removeRootAButton = new IButton (); removeRootAButton.setTitle ("Remove Root A"); removeRootAButton.addClickHandler (new ClickHandler () { public void onClick (final ClickEvent event) { tree.remove (rootATreeNode); } }); // button to delete the root final IButton removeRootARecursiveButton = new IButton (); removeRootARecursiveButton.setTitle ("Remove Root A Explicit"); removeRootARecursiveButton.addClickHandler (new ClickHandler () { public void onClick (final ClickEvent event) { removeTreeNodeExceptForRootTreeNode (tree, rootTreeNode); } }); // button to dump the tree final IButton dumpTreeButton = new IButton (); dumpTreeButton.setTitle ("Dump Tree"); dumpTreeButton.addClickHandler (new ClickHandler () { public void onClick (final ClickEvent event) { final TreeNode treeNode = tree.getRoot (); final String prefix = " "; dumpTreeNode (tree, treeNode, prefix); } }); // layout final VLayout layout = new VLayout (); layout.addMember (treeGrid); layout.addMember (loadButton); layout.addMember (removeRootAButton); layout.addMember (removeRootARecursiveButton); layout.addMember (dumpTreeButton); layout.show (); } /** * Dumps the given TreeNode * @param tree * @param treeNode * @param prefix */ private void dumpTreeNode ( final Tree tree, final TreeNode treeNode, final String prefix) { // log GWT.log ( prefix + "id: " + treeNode.getAttributeAsInt (tree.getIdField ()) + "parentId: " + treeNode.getAttributeAsInt (tree.getParentIdField ()) + ""); // dump children final TreeNode[] childTreeNodeArray = tree.getChildren (treeNode); if (childTreeNodeArray != null) { for (final TreeNode childTreeNode : childTreeNodeArray) { dumpTreeNode (tree, childTreeNode, prefix + prefix); } } } /** * Removes the given TreeNode and all its children * @param tree * @param treeNode */ private void removeTreeNodeExceptForRootTreeNode ( final Tree tree, final TreeNode treeNode) { // remove children first final TreeNode[] childTreeNodeArray = tree.getChildren (treeNode); if (childTreeNodeArray != null) { for (final TreeNode childTreeNode : childTreeNodeArray) { removeTreeNodeExceptForRootTreeNode (tree, childTreeNode); } } // finally remove this node, unless it is the root if (treeNode.getAttributeAsInt (tree.getIdField ()) != 1) { tree.remove (treeNode); } else { GWT.log ("removeTreeNodeRecursive (): not deleting rootTreeNode"); } } }
Comment