Login Register

dojo.data.ItemFileWriteStore

Dojo core provides the ItemFileWriteStore store as an extension to ItemFileReadStore that adds on the dojo.data.api.Write and dojo.data.api.Notification API support to ItemFileReadStore. It was specifically created as a separate class so that if you only need read capability, you do not incur the download penalty of the write and notification API support if you won't use it. If your application needs to write to the ItemFileStore instead of just Read, then ItemFileWriteStore is the store you should instantiate. The input data format is identical to ItemFileReadStore.

The following dojo.data APIs are implemented by ItemFileWriteStore

  • dojo.data.api.Read
  • dojo.data.api.Write
  • dojo.data.api.Identity
  • dojo.data.api.Notification

Constructor Parameters

The constructor for ItemFileWriteStore takes the same parameters as ItemFileReadStore these are the following possible parameters in its keyword arguments:

url
The URL from which to load the JSON data. This is optional.
data
The JavaScript object that represents the stores contents, as defined by the previous structure. This is optional.
typeMap
A JavaScript associative map of data types to deserialize them. This is optional. See the Custom Data Type Mapping for more details.

Custom Data Type Mappings

The custom type mapping for the ItemFileWriteStore follows the same conventions as the ItemFileReadStore. The only caveat is, that for general purpose mappings, you must also provide a serialize function for mapping so the data can be rendered back out appropriately. For simple mapping, object.toString() is sufficient.

Simple Mapping: Direct Constructor

The direct constructor approach is the simplest way to map a type. This one assumes that the value stored in _value can be used as the parameter to the constructor for an object. When serializing this back to the ItemFileFormat, this assumes that object.toString() is sufficient for the _value value as shown in the following example:

var typeMap = {
                 "Color": dojo.Color,
                 ...
              };

General Purpose Mapping

The general purpose mapping is intended for cases in which you cannot directly pass the value of _value into a constructor. A good example of this is how Date is mapped internally in the ItemFileReadStore. This is used because ItemFileReadStore reads in the _value for a date as a serialized ISO string, which is not a format the general JavasScript Date object understands.

The following example shows date serialization and deserialization mapping:

var typeMap = {
                  "Date": {
                             type: Date,
                             deserialize: function(value){
                                 return dojo.date.stamp.fromISOString(value);
                             },
                             serialize: function(object){
                                 return dojo.date.stamp.toISOString(object);
                             }
                          }
              };

Query Syntax

The query syntax for ItemFileWriteStore is identical to the query syntax of ItemFileReadStore so see that section for more information.

Usage Examples

For these examples, we'll assume a datasource as defined by the following example data:

{ identifier: 'abbr',
  label: 'name',
  items: [
    { abbr:'ec', name:'Ecuador',           capital:'Quito' },
    { abbr:'eg', name:'Egypt',             capital:'Cairo' },
    { abbr:'sv', name:'El Salvador',       capital:'San Salvador' },
    { abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
    { abbr:'er', name:'Eritrea',           capital:'Asmara' },
    { abbr:'ee', name:'Estonia',           capital:'Tallinn' },
    { abbr:'et', name:'Ethiopia',          capital:'Addis Ababa' }
]}

Example 1: Add in a new country

var store = new dojo.data.ItemFileWriteStore({url: "countries.json"});
var usa = store.newItem({abbr: 'us', name: 'United States of America', capital: 'Washington DC'});

function saveDone(){
    alert("Done saving.");
}
function saveFailed(){
    alert("Save failed.");
}
store.save({onComplete: saveDone, onError: saveFailed});

Example 2: Delete a country

var store = new dojo.data.ItemFileWriteStore({url: "countries.json"}); function saveDone(){ alert("Done saving."); } function saveFailed(){ alert("Save failed."); } var gotNames= function(items, request){ for (var i = 0; i < items.length; i++){ console.log("Deleted country: " + store.getLabel(item); store.deleteItem(items[i]); } store.save({onComplete: saveDone, onError: saveFailed}); } var request = store.fetch({query: {name:"Egypt"}, queryOptions: {ignoreCase: true}, onComplete: gotNames});

Custom Saving

The save method by itself only updates the in-memory copy. To write the store back to the server, you need to override the extension point "_saveCustom". In markup language, it'd look something like:

You could also extend ItemFileWriteStore using Dojo's inheritance facilities:

dojo.declare("CustomItemFileWriteStore", ItemFileWriteStore, {
        _saveCustom: function(saveCompleteCallback, saveFailedCallback){
                //  xhrPost/xhrPut your data back to your server (convert it to the server format first if need be)
                // 'this' keyword refers to the ItemFileWriteStore instance being extended
                saveCompleteCallback();
        }
});

Further examples

For further examples refer to the Using Datastores section of the Dojo book or refer to the test cases for dojo.data provided in the tests sub-directory of your dojo distribution.

Looking at the code, this doesn't work

I tried using store.newItem(), passing it an item of the form {attr:"value"}, but the store threw an exception at me that it can't figure out the identity of the item ("newItem() was not passed an identity for the new item"). I skimmed through the ItemFileWriteStore source code and in newItem(), I stumbled upon this:

		var newIdentity = null;
		var identifierAttribute = this._getIdentifierAttribute();
		if(identifierAttribute === Number){
			newIdentity = this._arrayOfAllItems.length;
		}else{
			newIdentity = keywordArgs[identifierAttribute];
			if (typeof newIdentity === "undefined"){
				throw new Error("newItem() was not passed an identify for the new item");
			}
			if (dojo.isArray(newIdentity)){
				throw new Error("newItem() was not passed an single-valued identity");
			}
		}

Not sure what this snippet is supposed to achieve, but it couldn't ever work, because this._getIdentifierAttribute() plain and simply always returns "true". This is because _getIdentifierAttribute() simply looks up what value "dojo.data.api.Identity" has in the feature map. Well, it has the value "true", because the base class ItemFileReadStore implements the Identity API.
Going back to the code snippet above, this is what it always does:
1) Evaluate (identifierAttribute === Number) --> is always false, because "true" is not a Number
2) In the else block: newIdentity = keywordArgs[true] --> always yields "undefined", obviously.

The code above doesn't make any sense to me, is this a flaw or am I just horribly missing something?

PS: The code tags to format source code in a post don't work.

RE: Looking at the code, this doesn't work

I worked through the example and got the FileWriter to work, sort of (Can't get it to work for mulitple objects with children).
I'm using a webservice to get a JSON object and using it as a store for the digit.Tree. So what I did to get it working was to define a global variable I will use for the store along with the header I will use for the JSON object so I have:

var topStructure = {identifier: 'name', label: 'name', items: []};
var someThing = new dojo.data.ItemFileWriteStore({data: topStructure});

The identifier in the code that you mention (var identifierAttribute = this._getIdentifierAttribute();) is going to bet set as 'name', as I've set this in the first bit of code I do (var topStructure = {identifier: 'name', label: 'name', items: []};). Then when I pass this through to the constructor for the new FileWrite the identifer gets set.

Now to use the newItem is easy you can simply say: -

someThing.newItem({ name:'anotherParent' ,type:'Directory' ,directoryPath: 'C:\\data\\anotherParent'});

And it will add it to the dataStore.

Thanks

Chris

Yeah, I did a full text

Yeah, I did a full text search on the _features map which is returned by getFeatures() which in return is used by _getIdentifierAttribute(), and it looks as if it's being abused to actually store the identifier attribute... ugly! The feature map should hold the features, mapped to their boolean value and nothing else. If we need to store attribute identifiers, then this belongs into a separate object (separation of concerns = A Good Thing (tm)). It's just completely irritating to see the feature map serve two completely different things.

I also tried

I also tried with dojo.data.ItemFileWriteStore

var store = new dojo.data.ItemFileWriteStore({url:"countries.json"});
        var sl = store.newItem({name: 'Sri Lanka', capital: 'Columbo'});
store.save({onComplete: saveDone, onError: saveFailed});

firebug is giving an error in newItem...

If this is not the way what should be done?

There was a mistake in the

There was a mistake in the example. It was missing the abbr attribute as part of the newItem call. This is required because the dataset stated abbr was the identifier, and all items then must have a unique abbr attribute. This has been corrected in the book page example. Sorry about that.

newItem() error

FireBug Reports:

newItem() was not passed an identity for the new item

The corrected code is:

var usa = store.newItem({abbr:"us",name: 'United States of America', capital: 'Washington DC'});

You need to provide an "abbr" item, as described by the "identifier" JSON input data.

--
ChieftainY2k

Save was "Done"

I did the above and got "Save Done" in the alert. However, nothing happened in the grid. I used console.dir(store) before the save and see my new item in pending. And after the save it is no longer there and appears under _itemsByIdentity. I am not sure what I need to do to make the grid refresh. Any ideas?

dojo.data.ItemFileWriteStore is not a constructor

Hello all,

i've got a problem with initializing a ItemFileWriteStore:
The following code only gives back the Error-Message: "dojo.data.ItemFileWriteStore is not a constructor"

var myData = { identifier: 'abbr',
label: 'name',
items: [
{ abbr:'ec', name:'Ecuador', capital:'Quito' },
{ abbr:'eg', name:'Egypt', capital:'Cairo' },
{ abbr:'sv', name:'El Salvador', capital:'San Salvador' },
{ abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
{ abbr:'er', name:'Eritrea', capital:'Asmara' },
{ abbr:'ee', name:'Estonia', capital:'Tallinn' },
{ abbr:'et', name:'Ethiopia', capital:'Addis Ababa' }
]};

var theStore = new dojo.data.ItemFileWriteStore({data: myData});

What do i do wrong?

Thanks a lot!!

That is usually the result

That is usually the result of one of the below:

1. The dojo.require("dojo.data.ItemFileWriteStore"); is missing.

2. The constructor statement occurs before dojo has completed loading. Solution: Put the constructor in a function called by the init function in dojo.addOnLoad(init);.