View Full Version : Server Response to a JSONWriter

17 Nov 2009, 6:46 PM

I have been looking at this problem for over a week and am not getting anywhere. After much searching the web, forums and my innermost feelings, I turn to this forum in the hopes of finding peace, harmony and a solution.

I have setup an EditorGrid that has a JSONReader and writer. I am allowing multiple changes and then saving them as a batch with a save button. My challenge is with the phantom records. They are saved to the database and a success message is sent back along with the records so that the ID's can be updated. This is where everything goes wrong.

Let's say I send two records down to be created, Test1 and Test2 that will be assigned id's 1 and 2 in the database. My JSON response is:

{success: true,
data: [{id: 1, description: 'Test 1' },
{id: 2, description: 'Test 2' }
This is received and appears to be decoded properly. My problem comes when the id's are to be mapped back to the records in the grid, to replace the generated id's. Callback onCreateRecords is called passing the recordset and the response data. They are both arrays of hashes.

This is where the breakdown appears to happen. this.reader.realize(rs, data) is called which tests and verifies that both rs and data are arrays. This calls the line

this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift())
I know that this is supposed to recurse through all the records in the arrays and then eventually assign all the id's back into the record store. What I am seeing is instead it leaves both the rs and data arrays empty meaning there is nothing left to be reassigned to rs. End result, no record id's are updated.

If I only allow a single record update and return a simple hash rather than an array, everything works fine. Given that I want to do multiple records, I believe I should be returning an array of hashes.

Any help with the above would be much appreciated.

Thanks All

19 Nov 2009, 6:58 PM
After much digging, I think I found the real source of my issue. It turns out that the record ID's are updating exactly they are expected. What got me started down this path was a problem I was having with deleting records that were added and saved without reloading the grid.

What appears to be happening is that the datastore is updating the record ids with what is sent back from the server, but does not update the stores data.key values. The stores remove record method tries to get the index by id based on the key values in the store. As they were never updated by the save method, there is no match found and so the record does not get deleted from the store.

I am not sure if this is bug or note, but as a work around, on a successful write, I will use the write listener on the store to update the key values which should resolve the above issues.

Cheers .....

21 Nov 2009, 6:10 AM
New symptom,

While my workaround appears to be working I noted something different. When I check the parameters passed to the write listener on the datastore, the recordset, result and transaction.data are all empty arrays. The callback function appears to be deleting all the records as it recurses through the response message. This means there is not data in these values to be passed to the listener.

I am still not sure if this is a bug or not, but I gotta think that this functionality would have been well tested by now so it must be something I am doing.

Any thoughts on this?

21 Nov 2009, 4:29 PM
Latest Update:

Still chasing this and am running in circles. I am back to what I noted in the first posting. When I return from the realize method, rs and data have been cleared out by the shift() action. This means when you return back to onCreateRecords, rs is empty so there is nothing to pass to the reMap method.

End result is that the key values, etc. do not get remapped since there was nothing to pass in the first place. This one has been driving me nuts so I would really appreciate any assistance anybody can offer as this is driving me up the freakin wall.

Thanks ....

22 Nov 2009, 8:28 AM

I believe I have gotten to a point where I can close this out. After combing through many samples that are considered working, it has come clear that the behaviour I am seeing is expected. My delete problem simply comes down to the fact that I am deleting the grid object after the call to the database so I have lost the reference. I could get it back by getting the selected cell again and everything would work as expected or I could do it by id if I update the key values on a write. My choice .... I will update the key values on a successful write and use the returned id. Reason, just want to ensure there is no chance of getting out of sync with the server and also want to ensure there is possibility of supporting a mult-select delete.

There is an opinion here that I want to add in. I believe the batch handling of records in Ext.data.Store is still a little on the basic side. The capability is there but it does not appear to handle all of the clean up activities necessary to fully sycnhronize the store with the database and cannot handle errors on individual records. All or nothing on a batch save is usually not the best plan.

Just my thoughts and I appreciate all of those who had a read. Hopefully this chain will prevent some others from losing time chasing this and will jump right to a work around. In my case, I have done what I suggested in one of my earlier posts ... I have a write listener on the store that will update all of the data.keys for the new records.

Cheers All .... \:D/

22 Nov 2009, 2:42 PM

I promise this will the last time I update on this ... mostly because it is now working the way I want and so I am no longer going to look at this issue. I still believe that there is a design error in the way multi-value responses are handled resulting in the reMap method not getting called properly. I invite any of the EXTJS staff to show me the error in my ways, but I cannot see the where's and why for's ...

So what I have done is created a listener on the datastores write event. When a save is completed the listener calls onWrite which calls the reMap method. This corrects all of the issues. I am not happy with this approach as it relies on calling an internal method which is never a good thing. At some point in the future I will rewrite this part of the grid handling to give me the ability to handle mutli-record arrays along with individual record errors etc. Of course that will need to be at a future point as I have already spent too much time on this, but I will get back to it (ya, how often have you heard that one ... ).

Anyway, for those who are interested, here is my listener code.

onWrite: function(store, action, result, transaction, recordStore){
// TODO: Decide if we want to handle return messages

if (action == 'create') {
// TODO: Ensure group header and topics are updated
for (var counter = transaction.phantomIDs.length; counter > 0; counter--) {
var record = this.getById(transaction.phantomIDs[counter - 1]);