0

I've been using dgrid 0.3.2 along with JsonRest to display tables of data. Recently, I've been looking at upgrading to dgrid 0.3.6 or 0.3.7. Things work mostly the same, but it seems with the newer versions of dgrid that, if the user clicks a column header to sort fast enough, the grid will start displaying duplicate rows. I’ve verified that the response JSON and range are correct, and this didn’t seem to happen when we used dgrid 0.3.2.

Here’s a simple test case that reproduces the problem, and mimics how we set up our grid and store. Am I doing something wrong? If I don’t wrap the JsonRest in a Cache, I don’t get this issue, so I’m sure the problem is there, but I’m unsure about the performance ramifications of not caching the JSON response.

<!doctype html>
<html>

<head>
<%
    String dgridVer = request.getParameter("dgridVer");
    if (dgridVer==null) { dgridVer = "0.3.6"; }
%>
<script type="text/javascript">
    var dojoConfig = {
        isDebug: true,
        baseUrl: 'dojo',
        packages: [
            { name: 'dojo',      location: 'dojo' },
            { name: 'dijit',     location: 'dijit' },
            { name: 'dojox',     location: 'dojox' },
            { name: 'dgrid',     location: 'dgrid-<%=dgridVer%>' },
            { name: 'put-selector',     location: 'put-selector' },
            { name: 'xstyle',    location: 'xstyle' },
            { name: 'datagrid', location: '../datagrid' }
        ]
    };
</script>
<script src="dojo/dojo/dojo.js"></script>
</head>

<body>
Try sorting a column as fast as you can.  Look for duplicated rows.<br>
Using dgrid version: <%=dgridVer %><p>

<div id='gridDiv'></div>

<script>
require(['dgrid/Grid', 'dgrid/extensions/Pagination', 'dojo/store/JsonRest',
            'dojo/store/Cache', 'dojo/store/Memory', 'dojo/_base/declare', 'dojo/domReady!'], 
    function(Grid, Pagination, JsonRest,
                Cache, Memory, declare) {

    var columns = [
        { field: "first", label: "First Name" },
        { field: "last",  label: "Last Name" },
        { field: "age",    label: "Age" }
    ];

    var store = new JsonRest({
        target: 'testData.jsp',
        sortParam: "sortBy"
    });
    store = Cache(store, Memory());

    var grid = new (declare([Grid, Pagination]))({
        columns: columns,
        store: store,
        loadingMessage: 'Loading...',
        rowsPerPage: 4,
        firstLastArrows: true
    }, 'gridDiv');

});
</script>

</body>

</html>
bobby_light
  • 726
  • 5
  • 14

1 Answers1

1

Check the default implementation of Cache.js, especially the query and queryEngine functions. By default they always get first to the master store, which in your case is the JsonRest store. Only after the data has been loaded, the caching store is updated (in your case the Memory store).

Now, if you check function _setSort in DGrid List.js file, and function refresh in DGrid OnDemandList.js you'll sill see that by default DGrid calls the query method of the current store to obtain the new list of items sorted differently. In your case that store is the dojo/store/Cache.

So, summing up, when the user clicks the column to sort, DGrid queries the Cache, which in turn queries JsonRest, which in turns queries the server, which then returns new data, which then the Cache stores in the Memory store.

You can actually confirm this for example with Firebug (a Firefox extension). In my case whenever I tried to sort, Firebug was showing a new request to the server to obtain new data.

This makes sense when there are lots of rows because DGrid is designed to load only the first batch of rows and then update the grid when user scrolls down. When the sort is changing, the first visible batch of rows may be different and may not be loaded yet, so DGrid must load them first.

But in my case the Json request was returning all data during a single request. I didn't like the default implementation and implemented my own caching store which doesn't require a trip to the server when changing the sorting. I can't share the implementation now but will try to do when I have some time to tidy up the code.

As for now you shouldn't notice any performance problems if you switch to JsonRest store only (considering that when changing the sorting there is the trip to the server anyway).

I am not sure what causes the specific problem of duplicated rows, but I remember seeing it too when my caching store wasn't implemented properly (it had something to do with deferred requests when loading data If I recall correctly). You can try to debug it by adding (again with Firebug) breakpoints in the get and query functions of the Cache store. My bet is that DGrid tries to load particular rows with the get method (which hits the cache) while the query request is still loading data from the server after user changed the sorting. But I may be wrong so please try to confirm it first if you can.

Greg
  • 8,230
  • 5
  • 38
  • 53
  • Sorry it took me so long to reply. Thanks for the response, and you were thinking what I was thinking. I couldn't figure out what had changed in the dgrid code, but did isolate it to 0.3.5 when this behavior changed. I created [issue 635](https://github.com/SitePen/dgrid/issues/635) and mentioned a workaround I came up with - simply disabling column sorting while a sort is currently running. – bobby_light Jul 18 '13 at 20:36