3

Firstly, I'm using dojo 1.1.0 and dgrid 0.4.0. I'm creating a page with a few dgrids on it. One grid in particular needs to load JSON data from a url and display it. It currently works fine doing that with a RequestMemory store. however, this is a "memory" store. while this might be trivial for some others, I need to find a way to load the data as it is being done now, and then add a refresh button to the screen that calls the necessary functions/methods to reload the data from the url and repopulate the dgrid.

The JSON data comes from the url formatted like this:

[{"id":1,"name":"trans1","username":"trans1","status":"Available","inactive":"no","checkedout":"false","details":"","assignedNum":"0","completedNum":"0","avgTime":"00:00","aaOn":true},{"id":2,"name":"trans2","username":"trans2","status":"Available","inactive":"no","checkedout":"false","details":"","assignedNum":"0","completedNum":"0","avgTime":"00:00","aaOn":true},{"id":3,"name":"trans3","username":"trans3","status":"Available","inactive":"no","checkedout":"false","details":"","assignedNum":"0","completedNum":"0","avgTime":"00:00","aaOn":false},{"id":4,"name":"trans4","username":"trans4","status":"Available","inactive":"no","checkedout":"false","details":"","assignedNum":"0","completedNum":"0","avgTime":"00:00","aaOn":false},{"id":5,"name":"trans5","username":"trans5","status":"Available","inactive":"no","checkedout":"false","details":"","assignedNum":"0","completedNum":"0","avgTime":"00:00","aaOn":false},{"id":6,"name":"trans6","username":"trans6","status":"Available","inactive":"no","checkedout":"false","details":"","assignedNum":"0","completedNum":"0","avgTime":"00:00","aaOn":false}]

The Require you'll see below actually contains much more than just this grid...hence all the extra.

I have no need to update the local store, nor do I want to monitor the url for changes. I simply want to be able to reload the data from the url on demand.

Here's the code I'm currently using for the initial loading of the grid (working) and the refresh button that I so need to get to work.

require([ 'dojo/store/Observable' ,'dijit/Dialog', 'dijit/form/Select', 'dijit/form/MultiSelect', 'dijit/form/TextBox', 'dijit/layout/TabContainer', 'dijit/layout/ContentPane','dojo/request', 'dojo/request/xhr', 'dijit/form/ToggleButton', 'dijit/form/Button', 'dojo/parser', 'dojo/_base/declare', 'dgrid/Grid', 'dgrid/Selection', 'dgrid/Editor', 'dgrid/extensions/ColumnHider', 'dgrid/extensions/Pagination', 'dstore/RequestMemory', 'dijit/form/Select', 'dijit/registry','dojox/data/XmlStore', 'dojo/domReady!'], function (Observable, Dialog, Select, MultiSelect, TextBox, TabContainer, ContentPane, request, xhr, ToggleButton, Button, parser, declare, Grid, Selection, Editor, ColumnHider, Pagination, RequestMemory, Select, registry, XmlStore) {


//workers dgrid
    var workersStore = new RequestMemory({ target: '/autoAssign/getWorkers.aa?TASKTYPE=transport&INACTIVE=FALSE' });        
    var workerGrid = new (declare([ Grid, Selection, Pagination, Editor, ColumnHider ]))({
        collection: workersStore,
        className: 'dgrid-autoheight',
        id: 'workerGrid',
        rowsPerPage: 6,
        columns: {
            name: 'Name',
            username: {
                label: 'username',
                hidden: true
            },
            status: 'Status',
            assignedNum: 'Assigned',
            completedNum: 'Completed',
            avgTime: 'Average',
            aaOn: {
        label: 'Auto Assign',
        editor: 'checkbox',
                  }
        }
    }, 'gridNode');
    workerGrid.on("dgrid-datachange",function(evt) {
       var row = workerGrid.row(evt); 
       if (evt.cell.column.id == 'aaOn') {
           var promise = request('/autoAssign/setUserAaStatus.aa?USERNAME='+row.data.username+'&TASKTYPE=transport&STATUS='+evt.value);
       }
    });
    workerGrid.startup();


//Add refresh Button
      var addRefreshButton = new Button({
        label: "Refresh",
        style: 'float:right;',
        onClick: function(){
           var promise = workersStore.fetch();
           var result = promise.then(function(data){
               workerGrid.set("collection", workersStore);
               workerGrid.refresh();
               alert("refresh pushed");
           });
        }
    }, "refresh").startup(); 


}

[{"id":1,"name":"trans1","username":"trans1","status":"Available","inactive":"no","checkedout":"false","details":"","assignedNum":"0","completedNum":"0","avgTime":"00:00","aaOn":true},{"id":2,"name":"trans2","username":"trans2","status":"Available","inactive":"no","checkedout":"false","details":"","assignedNum":"0","completedNum":"0","avgTime":"00:00","aaOn":true},{"id":3,"name":"trans3","username":"trans3","status":"Available","inactive":"no","checkedout":"false","details":"","assignedNum":"0","completedNum":"0","avgTime":"00:00","aaOn":false},{"id":4,"name":"trans4","username":"trans4","status":"Available","inactive":"no","checkedout":"false","details":"","assignedNum":"0","completedNum":"0","avgTime":"00:00","aaOn":false},{"id":5,"name":"trans5","username":"trans5","status":"Available","inactive":"no","checkedout":"false","details":"","assignedNum":"0","completedNum":"0","avgTime":"00:00","aaOn":false},{"id":6,"name":"trans6","username":"trans6","status":"Available","inactive":"no","checkedout":"false","details":"","assignedNum":"0","completedNum":"0","avgTime":"00:00","aaOn":false}]

Any help would be greatly appreciated. I was previously doing this with Dojo's old datagrid and just can't seem to grasp what I'm missing here.

Ken Franqueiro
  • 10,559
  • 2
  • 23
  • 40
BLWedge09
  • 39
  • 1
  • 6

1 Answers1

6

Technically, to do what you want, you do need to update the local store, in a way. dstore/RequestMemory is essentially a composition of dstore/Request and dstore/Cache, where a single fetch request is performed immediately and then the caching store fields all future fetch operations. In order to force the store to refresh from the server, you basically need to tell the store that its cache is no longer valid, then re-request all items from the server. This equates to the following:

workersStore.invalidate(); // Invalidate the cache
workersStore.fetch(); // Perform a new request for all items
workerGrid.refresh();

Once that fetch is performed, the Cache store will understand that it can then pull all requests from its in-memory store.

(The fetch call is important - if you don't call fetch above, your grid will probably not work as you expect. dgrid's OnDemandGrid and Pagination modules perform ranged queries using fetchRange, and unless Cache knows it has all of the store's data, it will simply let those pass through to the original store, which in this case is Request, which will try to hit the server - except your service is presumably not equipped to handle ranged queries, so it will just return the entire data set every time.)

Admittedly, I'd argue this is more information than someone using RequestMemory should need to know, so I'm probably going to submit an issue for some sort of API for refreshing and/or updating target. The 3 lines of code above are the TL;DR though.

Ken Franqueiro
  • 10,559
  • 2
  • 23
  • 40
  • Update: pull request submitted to make this easier: https://github.com/SitePen/dstore/pull/106 – Ken Franqueiro Feb 27 '15 at 05:15
  • THANK YOU! The invalidate() is exactly what I was missing. I had actually previously tried the fetch and then refresh() the grid...and it acted as if nothing happened. This worked perfectly. Amazing that I've been searching for 3 days and couldn't find that documented anywhere. – BLWedge09 Feb 27 '15 at 15:05
  • Ken, oddly enough I just realized a peculiarity about the simple version of the solution you posted. If records are added tho the url (the original datasource) the store updates with those records just fine. However,if records are removed from the original datasource, the store doesn't remove them. I was expecting it to fully reload the Requestmemory store from the url in both cases. Any suggestion as to how to make the deletion scenario work? – BLWedge09 Mar 03 '15 at 21:15
  • 3
    Man, that's a good catch. Can you try calling `workersStore.cachingStore.setData([])` right after invalidate? If that works, I'll add a note to my PR (not sure if I can really put that *in* the PR since technically I believe it's possible to use something other than Memory as the caching store). – Ken Franqueiro Mar 04 '15 at 02:15
  • Ken, yep that did it. Thanks again. Since you mentioned an alternative, what would you suggest using as the store (in the future) for my type of situation? What is better suited to make on demand calls from a URL that returns JSON? – BLWedge09 Mar 04 '15 at 14:45
  • If by "alternative" you are referring to me saying it's possible to use something other than Memory as the caching store, all I mean is that technically you can pass a store to `cachingStore` when instantiating, and it will use that instead of `Memory`. I'll add a comment to my PR and ask Kris how heavily-used/supported that case is expected to be. – Ken Franqueiro Mar 04 '15 at 17:15
  • Resurrecting this old thread because I find the advice here no longer seems true. I have a `RequestMemory` store (dstore 1.2.1) which has loaded its data for display in a dgrid (0.4.2). Calling `RequestMemory::refresh()` on the store causes it to call `Cache::invalidate()` which sets `this.allLoaded = false`, but then `refresh()` calls `fetch()` which calls `Cache::_fetch` checks `this.isAvailableInCache()` which tests `this.isValidFetchCache` which is true, so the cached data is used. I'm going nuts trying to make the Cache behave. Is there a discussion somewhere I've missed? – Neek May 14 '21 at 07:37