Hi there,
I'm working with the paged treegrid and I’m trying to get a solution to a usecase for the paged treegrid.
I have a scenario that I want to show a hierarchy of a company. Like shown in the examples. After opening multiple nodes, the scrollbar appears and the user can scroll within the treegrid.
Now I have the option that in the last depth (there are ony leaves returned after opening the node) the user can interact with this elements. For example the user can approve some of the shown elements in the last depth.
Through interaction, the user could now remove some nodes.
Now there are two possibilities:
1. To reflect the changes the user might have done, the tree could be set new.
This would result into a new datasource-request for the root-node. The problem is, that the treegrid does scoll up to the top, so the last seen nodes are not visible anymore. If you're lucky the node which was opened, is already visible and the datasource could return the request with "isOpne: true". If the user scrolled down (for the second set of child-nodes of the root), has opened a node and made an interaction, it is not possible to go there by now. It's not possible to use scrollToRow, because you dont know the row, where the parent-node of the interaction-node might be.
This results to: Everytime the user does any interaction with a treenode, the tree has to be created new and the tree will always jump to the top. Even if the datasource responds with "isOpen:true" at the right nodes which leads to the dedicated node, which should be opened.
Jumping to the top at every interaction is quite obstructively. This was already realized in the not paged treegrid. If you have a large tree, and open multiple nodes and scroll to the bottom you can interact with these nodes. If you now work with "tree.setRoot({...})" the scroll-bar stays at the same position and you can see the same nodes, as before.
2. The other possibility could be, to remove one specific node.
The API for that operation exists. Trying to work with this, does result in nothing, because the node will not be removed.
There is also a possibility that you might achieve a move-operation between the nodes (so one child gets a new parent), so you remove and add the node at a different position. I have only tested the remove()-operation, you can take a look at the example code below.
I think, there would be a third possibility, which sounds to me as the best solution.
If there would be the possibilty to reload the children of a specific node, it would solve the scrolling issue, and would also solve the removing issue. If the user tries to interact with the tree and you have to update some children you simply could start an "invalidateCache" on a specific (parent)node, and the tree would reload all of it's children. Because the rest of the tree stays untouched, there would be no need to scroll to the top again.
The only change, the tree would have to do, is to call the datasource for this specific node and copy the number of the attribute "totalRows" to the childCount of the specific node. Even the scoll-bar position could stay at the same position, because there would be no need to scroll to another position.
By now an "invalidateCache"-method is only implemented in the TreeGrid, so every time you call this, the whole tree gets reloaded. In other words, it's a invalidateCache on the root-node ;-)
I'm really interested in, what you think about this, and how to properly solve a change in the paged tree. For a "read-only" tree, the current implemented solution is quite good - and maybe the treegrid was created for a "read-only" use-case.
If you want to interact in a paged treegrid with the displayed treenode the scrolling to the top is really annoying (I have tested it out). Also I can understand why remove() is not functional with a paged treegrid, because you could not guarantee the synchronicity between the client and the server.
Best Regards
I'm working with the paged treegrid and I’m trying to get a solution to a usecase for the paged treegrid.
I have a scenario that I want to show a hierarchy of a company. Like shown in the examples. After opening multiple nodes, the scrollbar appears and the user can scroll within the treegrid.
Now I have the option that in the last depth (there are ony leaves returned after opening the node) the user can interact with this elements. For example the user can approve some of the shown elements in the last depth.
Through interaction, the user could now remove some nodes.
Now there are two possibilities:
1. To reflect the changes the user might have done, the tree could be set new.
This would result into a new datasource-request for the root-node. The problem is, that the treegrid does scoll up to the top, so the last seen nodes are not visible anymore. If you're lucky the node which was opened, is already visible and the datasource could return the request with "isOpne: true". If the user scrolled down (for the second set of child-nodes of the root), has opened a node and made an interaction, it is not possible to go there by now. It's not possible to use scrollToRow, because you dont know the row, where the parent-node of the interaction-node might be.
This results to: Everytime the user does any interaction with a treenode, the tree has to be created new and the tree will always jump to the top. Even if the datasource responds with "isOpen:true" at the right nodes which leads to the dedicated node, which should be opened.
Jumping to the top at every interaction is quite obstructively. This was already realized in the not paged treegrid. If you have a large tree, and open multiple nodes and scroll to the bottom you can interact with these nodes. If you now work with "tree.setRoot({...})" the scroll-bar stays at the same position and you can see the same nodes, as before.
2. The other possibility could be, to remove one specific node.
The API for that operation exists. Trying to work with this, does result in nothing, because the node will not be removed.
There is also a possibility that you might achieve a move-operation between the nodes (so one child gets a new parent), so you remove and add the node at a different position. I have only tested the remove()-operation, you can take a look at the example code below.
Code:
isc.VLayout.create({ "ID" : "rootLayout_5", "width" : "100%", "height" : "100%", "autoDraw" : true, "hideUsingDisplayNone" : false, "leaveScrollbarGap" : false, "members" : [ isc.Button.create({ title: "remove node 'root-1-3'", width: 200, click:function(){ theTreeGrid.data.remove(theTreeGrid.data.findById("root-1-3")); }} ), isc.TreeGrid.create({ "ID" : "theTreeGrid", "width" : "100%", "height" : "100%", "selectionType" : "multiple", "canEdit" : false, "showFilterEditor" : false, dataSource : isc.DataSource.create({ "fields" : [{ "name" : "treeGridGeneratedIndex", "primaryKey" : true, "hidden" : true, "canView" : false }, { "name" : "nameField", "title" : "Reason", "type" : "text" }, { "name" : "parentId", "rootValue" : "root", "foreignKey" : "treeGridGeneratedIndex", "hidden" : true } ], "dataFormat" : "json", "dataURL" : "http://devset.de/treegrid2.php", "transformRequest" : requestTransformer, "transformResponse" : responseTransformer, "recordXPath" : "\/resultData", useHttpProxy : false }), dataProperties : { openProperty : "isOpen", childrenProperty : "children", canReturnOpenFolders: true, progressiveLoading : false }, "autoFetchData" : true, "dataPageSize" : 50, "dataFetchMode" : "paged", "selectionProperty" : "isSelected", "fields" : [{ "name" : "nameField", "title" : "Reason", "type" : "text", "canEdit" : true, "canSort" : true }, { "name" : "lastField", "title" : "Name", "type" : "text", "canEdit" : true, "canSort" : true }, { "name" : "randomField", "title" : "random", "type" : "text", "canEdit" : true, "canSort" : true } ], "selectionProperty" : "isSelected", "members" : [] }) ] }); function requestTransformer(dataSourceRequest) { var operationType = { operationType : dataSourceRequest.operationType }; if (dataSourceRequest.operationType == "fetch") { var params = { delay: 300, sortBy : dataSourceRequest.sortBy, start : dataSourceRequest.startRow, end : dataSourceRequest.endRow }; } return isc.addProperties({}, operationType, dataSourceRequest.data, params); } function responseTransformer(dataSourceResponse, dataSourceRequest, jsonData) { if (dataSourceRequest.operationType == "fetch") { dataSourceResponse.totalRows = jsonData.totalRows; dataSourceResponse.endRow = jsonData.endRow; dataSourceResponse.startRow = jsonData.startRow; }; }
If there would be the possibilty to reload the children of a specific node, it would solve the scrolling issue, and would also solve the removing issue. If the user tries to interact with the tree and you have to update some children you simply could start an "invalidateCache" on a specific (parent)node, and the tree would reload all of it's children. Because the rest of the tree stays untouched, there would be no need to scroll to the top again.
The only change, the tree would have to do, is to call the datasource for this specific node and copy the number of the attribute "totalRows" to the childCount of the specific node. Even the scoll-bar position could stay at the same position, because there would be no need to scroll to another position.
By now an "invalidateCache"-method is only implemented in the TreeGrid, so every time you call this, the whole tree gets reloaded. In other words, it's a invalidateCache on the root-node ;-)
I'm really interested in, what you think about this, and how to properly solve a change in the paged tree. For a "read-only" tree, the current implemented solution is quite good - and maybe the treegrid was created for a "read-only" use-case.
If you want to interact in a paged treegrid with the displayed treenode the scrolling to the top is really annoying (I have tested it out). Also I can understand why remove() is not functional with a paged treegrid, because you could not guarantee the synchronicity between the client and the server.
Best Regards
Comment