Announcement

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

    Scrolling in paged TreeGrid results into loading all Children

    Hi there,

    I have a big paged tree (in the example with 1200 nodes). The advantages of a paged tree is, that the data is loaded when needed.

    A ListGrid with a DataSource does also quite a good job while loading only the data from the server, which are needed. For example while dragging the scrollbar to the bottom of a ListGrid with a Datasource. When first seeing the Listgrid the first x shown records are fetched (for example 1-37). When scrolling to the bottom the last records are fetched (for example 137-160). The data between these two groups are loaded when needed.

    This behaviour should also be in the paged treegrid, but it isn't. (Tested in the latest release of 10.1 SmartClient_v101p_2016-05-14_Pro).

    Here you can see I have a large treegrid, and drag the scrollbar to the bottom. I would assume the second request would only load the nodes between 1150-1200, but instead it load all nodes after the last node of the first request. Therefore the load is slower than working with listgrids(like described above load only the last x records), because it has to load a larger subset of the total nodes. Click image for larger version

Name:	Animation 45.gif
Views:	135
Size:	199.6 KB
ID:	237983



    Even if I press F5 the TreeGrid is build new and the data is loaded. It seems the TreeGrid is automatically scolling to the bottom, and also loads the complete tree with 2 requests. I can understand why there have to be 2 requests (to get the totalNum of nodes), but the second requests (same problem as above) shouldn't need to load all nodes after 50 to 1200: Click image for larger version

Name:	Animation 46.gif
Views:	75
Size:	273.1 KB
ID:	237984



    In addition: Is there a possibility to turn off this automatic scrolling after a page-refresh?

    This is the code for reproduction:
    Code:
    isc.VLayout.create({
    "ID" : "rootLayout_5",
    "width" : "100%",
    "height" : "100%",
    "autoDraw" : true,
    "hideUsingDisplayNone" : false,
    "leaveScrollbarGap" : false,
    "members" :
    [
    isc.Button.create({
    title: "take the scroller an drag it to the bottom",
    width: 200,
    click:function(){
    }}
    ),
    isc.TreeGrid.create({
    "ID" : "theTreeGrid",
    "width" : "100%",
    "height" : "300",
    "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://www.devset.de/treegrid4.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;
    };
    }
    Best Regards
    Last edited by SimonF; 18 May 2016, 04:40.

    #2
    You've explicitly set canReturnOpenFolders, which has the following warning of dire performance consequences in the docs (Tree DataBinding overview):

    .. by default the server is not allowed to return folders that are open, as this creates a potential performance issue: consider the case of a user scrolling rapidly into an unloaded area of the tree, skipping past many nodes that have not been loaded. If the skipped nodes might have been open parents, then the only way to know what nodes should be visible at the new scroll position is to load all skipped nodes and discover how many visible children they had.
    This is exactly what you're seeing.

    Comment


      #3
      Note further, the very next paragraph suggests setting progressiveLoading, which will then prevent people from scrolling to the end of the tree.

      When you combine 1) allowing users to jump immediately to an arbitrary position in the tree and 2) allowing the server to return folders already open, then you get this consequence of needing to load all the intermediate data.

      The only other approach is to have the server maintain the current open state of the tree, and have the client treat the data model as a list. You can do this with a ListGrid, using formatters to add indenting and clickable open/close controls. This of course has other serious drawbacks in terms of the amount of state being maintained for each user, and the work the server is performing to maintain a server-side concept of a tree.

      Comment


        #4
        Thanks for the reply.

        progressiveLoading seems to be the best option that I'll have.

        If I want to use a treeGrid with progressiveLoading this is surely no client-side setting. So instead like pointed out in the documentation this has to be done by the server.

        Setting the totalRows to a smaller number results also in the need of changing the childCount to a smaller number. If you don't change the childCount to a smaller number, after the initial request there is a wrong height of the scrollbar. Click image for larger version

Name:	Animation 50.gif
Views:	57
Size:	435.5 KB
ID:	238878


        Reading the documentation changing the childCount is not recommended (or supported?) (http://www.smartclient.com/docs/rele...reeDataBinding)
        If any child node is open, the rules are:
        The childCountProperty may be provided even if not required as long as it's consistent with the childrenProperty, and both may also be optionally specified for closed nodes. If the rule about providing children for each open node is violated, a warning will be logged and an immediate fetch issued for the missing children. Note that in the above DSResponse, or in general when paging is active, you can't supply mixed levels of nodes in the data as is described in the section "Multi-Level Load on Demand" above for simpler modes of ResultTree/Tree.
        Can you confirm this method, that by using the progressingLoading in a large paged TreeGrid you also have to set the childCount to a "wrong" (smaller) number?
        I'm just curious if this is the right, supported way to get this working.
        If it isn't, what's the correct way of dealing with a large paged TreeGrid with progressiveLoading?

        Best regards
        Simon
        Last edited by SimonF; 28 Jun 2016, 05:24.

        Comment


          #5
          See resultTree.progressiveLoading. Note that this means your server implementation needs to respect the progressiveLoading flag as well.

          Comment

          Working...
          X