Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    #16
    See tree.defaultIsFolder. Where you are currently thinking in terms of a "leaf becoming a folder", what you should instead do is return a folder, but explicitly indicate that it has zero children (as explained in the docs - be sure to follow the links to related docs). Then there will no fetch when it is opened, and there will also be no need for any kind of explicit conversion to a folder - just add child nodes to it.

    Comment


      #17
      Sorry I'm not following your first statement, see tree.defaultIsFolder?

      Comment


        #18
        We're referring to a property of the Tree class.

        Comment


          #19
          Thank you for that.

          I seem to be having issues with the timing of this call:
          Code:
          treeGrid.getData().setDefaultIsFolder(Boolean.TRUE);
          I either get a NPE or an error message saying I can't change the state after the component has been created?

          Comment


            #20
            See TreeGrid.dataProperties, and the notes on TreeGrid.fetchData() about when ResultTrees are created for you.

            Comment


              #21
              Originally posted by Isomorphic View Post
              Where you are currently thinking in terms of a "leaf becoming a folder", what you should instead do is return a folder, but explicitly indicate that it has zero children (as explained in the docs - be sure to follow the links to related docs).
              Thank you, I have a better understanding of setting default properties now by passing in a Tree instance to the TreeGrid for defaultProperties.

              I need a little more clarification about your next statement above. I don't follow you when you say 'what you should instead do is return a folder'?

              Comment


                #22
                You should return data from the server that will be treated as a folder.

                Whether it is treated as a folder is determined by tree.defaultIsFolder and the isFolderProperty.

                Comment


                  #23
                  I got you.
                  Code:
                  Tree treeConfig = new Tree();
                  treeConfig.setDefaultIsFolder(Boolean.TRUE);
                  treeGrid.setDataProperties(treeConfig);
                  Great.
                  As I click into my tree in the UI, I expand the root node, I see a DSRequest with parentID set go through good. The same with the second node and the third. Now what I see is a folder icon, but i know there is no more data below this folder in the UI. I click on it and I see a DSRequest with parentID in it, and I return an empty DSResponse
                  Code:
                              DSResponse dsResponse = new DSResponse();
                              dsResponse.setData(new ArrayList<Map<String, Object>>(0));
                              dsResponse.setStartRow(0);
                              dsResponse.setEndRow(0);
                              dsResponse.setTotalRows(0);
                  
                              return dsResponse;
                  And the folder icon dissapears and it's a leaf node now. I was expecting the folder icon to remain because of the treeConfig I set in the first code block above?

                  I think what is missing is a dummy Record with the parentId set to the leaf node, like you say return a folder instance with no real data and children set to zero.
                  Last edited by JLivermore; 4 Sep 2014, 15:45.

                  Comment


                    #24
                    Further testing with the same code in my previous post, I'm just simply trying to look at the node attribute data as a Folder first, then as a Node. I have a FolderOpnedHandler and LeafClickHandler as follows:
                    Code:
                    private class TreeGridFolderOpenedHandler implements FolderOpenedHandler {
                    
                            @Override
                            public void onFolderOpened(FolderOpenedEvent event) {
                                String cid = event.getNode().getAttributeAsString("cid");
                                String pid = event.getNode().getAttributeAsString("pid");
                                TreeNode treeNode = event.getNode();
                                String[] attributes = treeNode.getAttributes();
                                GWT.log("folder opened PID [" + pid + "] CID [" + cid + "]");
                                for(String attribute : attributes) GWT.log(attribute + " : " + treeNode.getAttributeAsString(attribute));
                            }
                        }
                    
                        private class TreeGridLeafClickHandler implements LeafClickHandler {
                    
                            @Override
                            public void onLeafClick(LeafClickEvent event) {
                                TreeNode treeNode = event.getLeaf();
                                String pid = treeNode.getAttribute("pid");
                                String cid = treeNode.getAttribute("cid");
                                String[] attributes = treeNode.getAttributes();
                                GWT.log("leaf clicked PID [" + pid + "] CID [" + cid + "]");
                                for(String attribute : attributes) GWT.log(attribute + " : " + treeNode.getAttributeAsString(attribute));
                            }
                        }
                    And then I add them to the TreeGrid:
                    Code:
                            treeGrid.addFolderOpenedHandler(new TreeGridFolderOpenedHandler());
                            treeGrid.addLeafClickHandler(new TreeGridLeafClickHandler());
                    For some reason, the LeafClickHandler is not firing? Below are the two Click outputs, the first one is when the folder at the bottom of the tree is clicked, it then becomes a leaf node in the TreeGrid (the folder icon goes away). And when I click again expecting to see the LeafClickHandler output, I see the FolderOpenedClickHandler output?
                    Code:
                    INFO: folder opened PID [Y^|^BRITAIN] CID [Y^|^BRITAIN^|^USD]
                    INFO: bAVWAPBP : -5.104461062806903
                    INFO: bIVWAPCPS : -1.4805621616059332
                    INFO: Shares : 1112097
                    INFO: bAVWAPCPS : -2.158569943423075
                    INFO: name : USD
                    INFO: PrinK : 47028.25902819824
                    INFO: pid : Y^|^BRITAIN
                    INFO: bAVWAPK : -24.00539179611206
                    INFO: bIVWAPK : -16.465286918640135
                    INFO: cid : Y^|^BRITAIN^|^USD
                    INFO: bPlcStrikeBP : -14.726909436191364
                    INFO: bIVWAPBP : -3.5011474402814286
                    INFO: bExeStrikeK : 113.40092843055726
                    INFO: $399 : Y^|^BRITAIN^|^USD
                    INFO: _parent_isc_ResultTree_0 : [object Object]
                    INFO: $42c : isc_ResultTree_0
                    INFO: _cachedLength_isc_ResultTree_0 : 1
                    INFO: isFolder : true
                    I cannot get the LeafClickhandler to fire? When I click the leaf node twice I get the FolderOpenedClickHandler to first again.
                    Code:
                    INFO: folder opened PID [Y^|^BRITAIN] CID [Y^|^BRITAIN^|^USD]
                    INFO: bAVWAPBP : -5.104461062806903
                    INFO: bIVWAPCPS : -1.4805621616059332
                    INFO: Shares : 1112097
                    INFO: bAVWAPCPS : -2.158569943423075
                    INFO: name : USD
                    INFO: PrinK : 47028.25902819824
                    INFO: pid : Y^|^BRITAIN
                    INFO: bAVWAPK : -24.00539179611206
                    INFO: bIVWAPK : -16.465286918640135
                    INFO: cid : Y^|^BRITAIN^|^USD
                    INFO: bPlcStrikeBP : -14.726909436191364
                    INFO: bIVWAPBP : -3.5011474402814286
                    INFO: bExeStrikeK : 113.40092843055726
                    INFO: $399 : Y^|^BRITAIN^|^USD
                    INFO: _parent_isc_ResultTree_0 : [object Object]
                    INFO: $42c : isc_ResultTree_0
                    INFO: _cachedLength_isc_ResultTree_0 : 1
                    INFO: isFolder : true
                    INFO: _isOpen_isc_ResultTree_0 : false
                    INFO: children : 
                    INFO: $40a : pivot_table_tree_fact_POF_384_682
                    INFO: $27g : loaded
                    INFO: _selection_24 : true

                    Comment


                      #25
                      I'm now returning a dummy Record setup as follows:

                      Code:
                                  DSResponse dsResponse = new DSResponse();
                                  Record record = new Record();
                                  record.setAttribute("cid", al.get(14));
                                  record.setAttribute("children", 0);
                                  dsResponse.setData(record);
                                  dsResponse.setStartRow(0);
                                  dsResponse.setEndRow(0);
                                  dsResponse.setTotalRows(0);
                      
                                  return dsResponse;
                      Now I'm seeing this warning in the log when I send that dummy Record back:
                      Code:
                      ERROR: 09:47:55.544:TMR6:WARN:Log:TypeError: Object doesn't support property or method 'getLength'
                      Stack from error.stack:
                          Arra.addList () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:423:145
                          Tree._linkNodes () @ com.anstca.tz.Main/sc/modules/ISC_Grids.js?isc_version=9.1.js:68:126
                          ResultTree.loadChildrenReply () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:2036:346
                          Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:282:42
                          Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:342:279
                          DataSource.fireResponseCallbacks () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:727:1
                          DataSource._completeResponseProcessing () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:724:1
                          DataSource._handleSCServerReply () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:2400:102
                          Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:282:42
                          Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:342:279
                      
                      com.smartgwt.client.core.JsObject$SGWT_WARN: 09:47:55.544:TMR6:WARN:Log:TypeError: Object doesn't support property or method 'getLength'
                      Stack from error.stack:
                          Arra.addList () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:423:145
                          Tree._linkNodes () @ com.anstca.tz.Main/sc/modules/ISC_Grids.js?isc_version=9.1.js:68:126
                          ResultTree.loadChildrenReply () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:2036:346
                          Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:282:42
                          Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:342:279
                          DataSource.fireResponseCallbacks () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:727:1
                          DataSource._completeResponseProcessing () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:724:1
                          DataSource._handleSCServerReply () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:2400:102
                          Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:282:42
                          Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:342:279
                      
                      	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
                      	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
                      	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
                      	at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
                      	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:172)
                      	at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:293)
                      	at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:547)
                      	at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364)
                      	at java.lang.Thread.run(Thread.java:744)

                      Comment


                        #26
                        Hi,
                        Your DSRequests and responses seem consistent with standard data-binding requests/responses for a load-on-demand tree, and your event handlers seem consistent with this behavior, with the data showing up as a folder (and never actually becoming a leaf).
                        The mystery really is why you would be seeing a leaf icon on this node (which everything else seems to indicate would be just an empty folder).

                        We can't reproduce that in our testing, so it seems there must be something special about your configuration which would be causing it.

                        Here's a trivially simple test case demonstrating a load-on-demand tree (backed by a client-only-dataSource). When you open the deepest-nested nodes, you'll see the opener icon (the "[+]") disappear, but the nodes continue to show a folder icon - they don't switch to the "leaf" icon as in your test case.

                        Despite its simplicity, this is pretty much exactly your scenario - a fetch is issued and for that innermost node, it returns an empty response. The tree reacts by hiding the "opener" icon, but doesn't show the "leaf" icon in place of the "folder icon".

                        Could you see whether you reproduce the same problem as you're seeing in your app if you drop this test case in your environment?

                        Code:
                        import com.google.gwt.core.client.EntryPoint;
                        import com.google.gwt.core.client.JavaScriptObject;
                        import com.smartgwt.client.data.DataSource;
                        import com.smartgwt.client.data.DataSourceField;
                        import com.smartgwt.client.types.FieldType;
                        import com.smartgwt.client.widgets.tree.Tree;
                        import com.smartgwt.client.widgets.tree.TreeGrid;
                        
                        public class TreeGridBindingTest implements EntryPoint {
                        
                        	@Override
                        	public void onModuleLoad() {
                        		getTreeGrid().draw();
                        		
                        	}
                        	
                        	private TreeGrid treeGrid;
                        	public TreeGrid getTreeGrid() {
                        		
                        		treeGrid = new TreeGrid();
                        		
                        		Tree treeConfig = new Tree();
                        		treeConfig.setDefaultIsFolder(Boolean.TRUE);
                        		treeGrid.setDataProperties(treeConfig);
                        		
                        		treeGrid.setDataSource(getTestDS());
                        		
                        		treeGrid.setWidth(400);
                        		treeGrid.setHeight(400);
                        		
                        		treeGrid.setAutoFetchData(true);
                        		// Load a node at a time!
                        		treeGrid.setLoadDataOnDemand(true);
                        		
                        		return treeGrid;
                        		
                        	}
                        	
                        	private DataSource testDS;
                        	public DataSource getTestDS() {
                        		
                        		testDS = new DataSource();
                        		testDS.setID("testDS");
                        		
                        		testDS.setClientOnly(true);
                        		DataSourceField pkField = new DataSourceField("pk",FieldType.INTEGER);
                        		pkField.setPrimaryKey(true);
                        		
                        		DataSourceField parentPkField = new DataSourceField("parentPk", FieldType.INTEGER);
                        		parentPkField.setForeignKey("pk");
                        		
                        		DataSourceField titleField = new DataSourceField("title", FieldType.TEXT);
                        		
                        		testDS.setFields(pkField, parentPkField, titleField);
                        		
                        		setupCacheData(testDS.getOrCreateJsObj());
                        		
                        		return testDS;
                        	}
                        	
                        	private native void setupCacheData(JavaScriptObject dataSource) /*-{
                        		var testData = [
                        			{pk:0, title:"root"},
                        				{pk:1, parentPk:0, title:"child 1"},
                        					{pk:11, parentPk:1, title:"child 11"},
                        				{pk:2, parentPk:0, title:"child 2"}
                        		];
                        			
                        		dataSource.setCacheData(testData);
                        	}-*/;
                        
                        }
                        Assuming not, this implies there's something special about your use case which is leading to this. You could probably substitute this dummy dataSource (or one very similar) into your live app and see if the problem reproduces. If so, you'll know it's an issue with the TreeGrid configuration - if not (i.e. if the problem only occurs with your dataSource), we know the problem is somehow to do with the way you're loading data.
                        Either way this will likely give you enough information to pinpoint what's going wrong and/or show us a test case we can use to see what's going wrong for you.

                        Thanks
                        Isomorphic Software

                        Comment


                          #27
                          Your example works like you describe in our environment. Thank you for posting that test example.

                          I think there is a disconnect between what we are talking about. It is the TreeGrid '+' opener icon we would like to maintain on our leaf nodes which was what I was trying to explain, but did not realize there is a difference between the opener icon '+' and folder icon, since we don't show a folder or leaf icon. We only show the opener icon '+' in our TreeGrid.

                          So what we would like to do is retain the opener icon '+' on our leaf nodes. Because the user may change the configuration of our tree and those leaf nodes may become folder nodes with further depth to them *after* the user makes some external adjustments.

                          To recap, the TreeGrid assumes all nodes being returned are folder nodes, great. As the user clicks into the depth of the tree, as they click on what IS an leaf node, the DSRequest gets sent and we know we are at the edge of our tree, so we can return a dummy record.

                          The question is, how can we retain the opener '+' icon after a leaf node has been queried for more data and there is no data to return? We want to retain the opener '+' icon after we query the leaf node with no data.

                          Is there a way to reset all leaf nodes that are opened (missing the '+' icon) back to having the '+' icon? Or ideally maintain the '+' icon even after the load on demand DSRequest is made and it returns a dummy record if needed?

                          Upon further testing, posting #25 above, returning that dummy record restores the opener '+' icon the first time, however, I still get that Stack error in the client side log when that dummy record is returned? Here is what I am returning:
                          Code:
                                  Map map = dsRequest.getCriteria();
                                  logger.debug("fetchPivotTableTreeData Criteria [" + map.toString() + "]");
                                  ArrayList<String> al = (ArrayList)dsRequest.getCriteria().get("spc");
                                  String groupByDimension = al.get(7);
                                  if("EDGE_OF_TREE".equals(groupByDimension)) {
                                      DSResponse dsResponse = new DSResponse();
                                      TreeNode record = new TreeNode();
                                      record.setAttribute("cid", al.get(14));
                                      record.setAttribute("children", 0);
                                      record.setAttribute("isFolder", true);
                                      dsResponse.setData(record);
                                      dsResponse.setStartRow(1);
                                      dsResponse.setEndRow(1);
                                      dsResponse.setTotalRows(1);
                          
                                      return dsResponse;
                                  }

                          Do you know if there is a missing attribute that is needed on the dummy record above to fix this error:
                          Code:
                          ERROR: 11:58:46.417:TMR2:WARN:Log:TypeError: Object doesn't support property or method 'getLength'
                          Stack from error.stack:
                              Arra.addList () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:423:145
                              Tree._linkNodes () @ com.anstca.tz.Main/sc/modules/ISC_Grids.js?isc_version=9.1.js:68:126
                              ResultTree.loadChildrenReply () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:2036:346
                              Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:282:42
                              Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:342:279
                              DataSource.fireResponseCallbacks () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:727:1
                              DataSource._completeResponseProcessing () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:724:1
                              DataSource._handleSCServerReply () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:2400:102
                              Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:282:42
                              Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:342:279
                          
                          com.smartgwt.client.core.JsObject$SGWT_WARN: 11:58:46.417:TMR2:WARN:Log:TypeError: Object doesn't support property or method 'getLength'
                          Stack from error.stack:
                              Arra.addList () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:423:145
                              Tree._linkNodes () @ com.anstca.tz.Main/sc/modules/ISC_Grids.js?isc_version=9.1.js:68:126
                              ResultTree.loadChildrenReply () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:2036:346
                              Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:282:42
                              Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:342:279
                              DataSource.fireResponseCallbacks () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:727:1
                              DataSource._completeResponseProcessing () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:724:1
                              DataSource._handleSCServerReply () @ com.anstca.tz.Main/sc/modules/ISC_DataBinding.js?isc_version=9.1.js:2400:102
                              Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:282:42
                              Class.fireCallback () @ com.anstca.tz.Main/sc/modules/ISC_Core.js?isc_version=9.1.js:342:279
                          
                          	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
                          	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
                          	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
                          	at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
                          	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:172)
                          	at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:293)
                          	at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:547)
                          	at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364)
                          	at java.lang.Thread.run(Thread.java:744)
                          I suspect this error is what causes the leaf node to not work anymore, because the second time I click on the leaf node with the opener '+' icon (restored from the first time I clicked on it returning the dummy record above), the opener '+' icon goes away and there is no DSRequest fetch being sent.
                          Last edited by JLivermore; 8 Sep 2014, 08:19.

                          Comment


                            #28
                            As part of 5.0 / 10.0 we've added an attribute "alwaysShowOpener" to control whether or not the +/- icon is displayed for empty folders.
                            We'll look at backporting that to 4.1 so you can take advantage of this feature. If it turns out not to be straightforward we'll let you know and try to come up with another solution.

                            Comment


                              #29
                              Great, thank you, looking forward to it.

                              Comment


                                #30
                                Ok - we've ported this property across. As of the next nightly 9.1 build, you'll be able to call 'setAlwaysShowOpener(true)' on your treeGrid and the opener icon will be displayed for folders with no children (as well as those with children)

                                Regards
                                Isomorphic Software

                                Comment

                                Working...
                                X