PDA

View Full Version : JsonStore with JsonWriter, how to do it correctly



Sgt.Pepper
21 Apr 2010, 2:31 AM
Hello guys,

I've been messing around with EditorGrids, JsonStores, Writers and stuff for quite some time now. However I still have the feeling that I have not completely understood how Ext would like me to design the data flow, especially how to handle the CREATE requests.

I'm a little bit confused. In the book ExtJsInAction, there is a example with an EditorGrid, however data creation is handled by a generic Ajax call, followed by a store.comit(). Not exactly the native Ext way...

So let me give an example:

This is my store:



store : new Ext.data.JsonStore({
autoDestroy : true,
url : this.dataUrl,
idProperty : 'A',
root : 'data',
fields : ['A', 'B', 'C', 'E', 'D', 'F'],
autoLoad : true,
sortInfo : {
field : 'A',
direction : 'ASC'
},
autoSave : false,
writer : new Ext.data.JsonWriter({
encode : true,
writeAllFields : true

})

})
Of course this store is connected to an EditorGrid (which just displays all fields, and allows Editing via a TextField).
I've got some Buttons (add, delete, save) and a custom save function:



onSave : function () {
this.grid.stopEditing()
this.grid.store.save()
},
Now I create a new record in the Grid. I enter some values (A='myNewRecord', B='hello world').

When I press the save button, I would expect to see a request like this:


data {"A":"myNewRecord","B":"hello world"}however what I get is this

data {"A":"ext-record-19","B":"hello world"}My question:


Is there some native way, to make Exts accept the value that I just entered into A as an ID, thus forget about the ext-record-19?

bocockli
21 Apr 2010, 6:53 PM
Hi

Short answer, no, and you wouldn't want to.

When you call save() on a record, ExtJS will make the Record.id 'ext-record-xxx' unless you override it to create a unique number. Take a look at Record API in the documentation.



PREFIX : StringExt.data.Record.PREFIX (defaults to 'ext-record')
AUTO_ID : StringExt.data.Record.AUTO_ID (defaults to 1 initially)

Irrespective of how it generates the ID, you have to reconcile this to the server generated unique ID.

So say you are INSERTING a new record into the Store. You save() and the client will send the new record with an ID of ext-record-xxx'. You do an insert into the server side database, and the database will insert a new row into the table and return a new unique row ID. In your server code, you return this ID to the ExtJS client with the original 'ext-record-xxx' , and ExtJS will update the store record with the new server side ID.
The point is this : the server must be responsible for generating a unique record ID - the ExtJS can't because the Ext-JS store is transient.

So now another gotcha. The default ExtJS behavior allows you to create/update a Store record and then commit - the update of the ExtJS record with server side updates is done in the two functions Ext.data.JsonReader:realize and Ext.data.JsonReader:update. However, ExtJS expects back all the record data - not just the new ID - and it expects it in the same order has it was sent. Stupid, perhaps, but safe. If you don't do this, the record in the store will end up a new ID but blank!

I have decided to override both realize and update to just accept the new ID - it saves sending all the data back again. Like this




Server Receives:

14Apr2010 08:18:07 DEBUG arg[0]=vehicle
14Apr2010 08:18:07 DEBUG arg[1]=[{"recordID":"ext-record-124","customerID":1.etc etc...
14Apr2010 08:18:07 DEBUG arg[2]=create

Server Returns:
14Apr2010 08:18:07 DEBUG returning primary keys to client. JSON={"vehicle":[{"recordID":1,"clientRIDValue":"ext-record-124"}],"success":true}
You might want to use JSONReader and JSONWriter and HTTPProxy in the store as I do; watch also that a single record send from JSON is not as an array and mutli-record is. Also there is no commit for a destroy(); and the data sent by the JSONWriter is not JSON, rather:


21Apr2010 22:07:00 DEBUG http request: store=item;item=52;action=delete;Len