January 15, 2009

dojo.data.ItemFileWriteStore

when starting to use the dojo data API, the first store that most people learn to use is the dojo.data.ItemFileReadStore (read only) and it's counterpart dojo.data.ItemFileWriteStore (read & write). out of the box, dojo.data.ItemFileWriteStore (IFWS) doesn't actually have a mechanism to write anything anywhere. everything is in place to write, but the functions that actually do the writing are essentially a no-op and so you have to write your own. this is something that is not clearly obvious when you start to use IFWS and so it needs to be clearly stated. also, here is a simple example of writing to your server URL. NOTE: IFWS is not a very efficient store since ALL the data is written each time the store is saved.

the complete example is available here

here's the javascript:

dojo.require("dojox.grid.DataGrid");
dojo.require("dojo.data.ItemFileWriteStore");
dojo.require("dijit.form.Button");

var fillStore = function(){
dojo.xhrGet({
url: "samfuqua.json",
handleAs: "json",
load: function(data, ioArgs){
dijit.byId('table').setStore(new dojo.data.ItemFileWriteStore({
data: data
}));
dijit.byId('table').store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
console.log(newFileContentString);
dojo.xhrPost({
url: "yourURL",
postData: dojo.toJson(dojo.fromJson(newFileContentString)), // this unprettifies the string
error: saveFailedCallback,
load: saveCompleteCallback
});
}
}
});
}

dojo.addOnLoad(fillStore);


and here's the html:

<body class="tundra">
<button dojoType="dijit.form.Button" onclick="dijit.byId('table').store.revert();">Revert</button>
<button dojoType="dijit.form.Button" onclick="dijit.byId('table').store.save();">Save</button>
<table id="table" dojoType="dojox.grid.DataGrid">
<thead>
<tr>
<th field="genre">Genre</th>
<th field="author" editable=true>Author</th>
<th field="title">Title</th>
<th field="price">Price</th>
</tr>
</thead>
</table>
</body>


the part to focus in on is this section here:

dijit.byId('table').store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
console.log(newFileContentString);
dojo.xhrPost({
url: "yourURL",
postData: dojo.toJson(dojo.fromJson(newFileContentString)), // this unprettifies the string
error: saveFailedCallback,
load: saveCompleteCallback
});
}


for IFWS to actually do something, you have to override either the _saveEverything or the _saveCustom functions. in this case, we are overriding _saveEverything. when IFWS calls the _saveEverything function it will pass a saveCompleteCallback, saveFailedCallback and a newFileContentString. conveniently, these are basically what we would need to have to make an xhrPost to our server :)

the xhrPost is fairly straightforward, you provide a url, some data, an error callback and a load (success) callback. the only manipulation we've had to do here is "unprettify" the newFileContentString. when newFileContentString is passed in, it is a "prettified" json string - ie it has tabs, and newlines, etc. to format the string so that it looks "pretty" when it's printed. this is nice if you're writing the text directly to a file but this can cause problems if your server needs to understand the data so to unprettify it, i've converted the json to an object and then back to json again without prettifying it.

this is just a quick look at IFWS and for a more complete look at it, take a look at the docs at dojocampus