PDA

View Full Version : ExtJS 4.2.1 - Issues with sync on deleted records and on newly-created/edited records



jstricker
15 Jan 2014, 11:27 AM
I'm seeing three odd behaviors with an Ext.data.Store and Ext.grid.Panel in 4.2.1.
Items that are newly added (i.e. panel.store.add({}) ) cannot be removed (i.e. panel.store.remove(selectedRecord) ). There are no errors; it simply does nothing. Items that were auto-loaded from the store behave as I would expect.
If I remove two items (e.g. item with id 21 and item with id 22) right after each other, the second call fails. The first call to store.remove() triggers a sync that sends the first item (which succeeds--see JSON below) and calls the onDestroyRecords method with success set to true. The second call to remove triggers a sync that sends the first item again (which fails, obviously), and the second item (which succeeds) and calls the onDestroyRecords with success set to false.

{"success":true}
When I add a new item to the store (i.e. panel.store.add({}) ), the store calls the create service on the proxy and returns a new object (see JSON below) with properly defaulted values. Note that "fieldOne" is required in the database and that an id is assigned when the record is inserted, so the initial create returns an object with the id set to null.

{"success":true,"data":{"id":null,"fieldOne":null,"fieldTwo":"MEDIUM"}}

After editing fieldOne in the grid, the auto-sync is triggered. The server responds with the following JSON.

{"success":true,"data":{"id":75,"fieldOne":"Test","fieldTwo":"MEDIUM"}

While the id is present in the response, it does not get updated in the store. If I inspect store.data.items, I can see that the id is still null. I suspect this is related to the phantom attribute getting set to false in Reader's extractData() method on the initial create. I admittedly don't know the formal definition of what phantom means, but I would wager a guess that any time the id is undefined or null, phantom should be true.
Here's what my code looks like:



Ext.define("Example", {
extend: "Ext.data.Model",
idProperty: "id",
fields: [
{name: "id", type: "string", useNull: true},
{name: "fieldOne", type: "string"},
{name: "fieldTwo", type: "string"}
]
});

Ext.create("Ext.data.Store", {
storeId: "ExampleStore",
model: "Example",
autoLoad: true,
autoSync: true,
pageSize: 20,
remoteFilter: true,
remoteSort: true,
sorters: [
{property: "fieldOne", direction: "ASC"}
],
proxy: {
type: "ajax",
batchActions: false,
api: {
create: "/app/foo/createExample",
read: "/app/foo/listExample",
update: "/app/foo/saveExample",
destroy: "/app/foo/deleteExample"
},
reader: {
type: "json",
root: "data",
successProperty: "success",
messageProperty: "errors",
totalProperty: "total"
},
writer: {
type: "json"
},
simpleSortMode: true,
startParam: "offset",
limitParam: "max",
sortParam: "sort",
directionParam: "order",
},
onCreateRecords: function(records, operation, success) {
if (!success) {
// error handling removed for example
}
},
onUpdateRecords: function(records, operation, success) {
if (!success) {
// error handling removed for example
}
},
onDestroyRecords: function(records, operation, success) {
if (!success) {
// error handling removed for example
}
}
}).on({
beforeload: function(store, operation, eOpts) {
this.proxy.setExtraParam("fooId", $("#id").val());
},
beforesync: function(options, eOpts) {
this.proxy.setExtraParam("fooId", $("#id").val());
}
});

jstricker
16 Jan 2014, 3:37 PM
Does anyone have thoughts on these issues? Even wild guesses or vague pointers would be appreciated!

arnoldvillasanta
23 May 2014, 2:20 AM
Although this is an old post, I'll post my learnings here anyway.

When create/update works at the backend (you see the right data in the database being added/created), but are quite not what you've expected in the UI, because:

For CREATE calls, (where ID is created in the back-end), the newly created record 'might' appear in the gridpanel (or any other cmp), thinking that the backend ID is fetched from the backend "auto-magically"... but it's not. Try to console.log that record's ID and it will be "null" or ""... or referencing that record thru its ID will be "undefined".
You need to store.load() the store somewhere (best in a callback... but I guess SYNC doesn't have that yet...)

If you UPDATE a record, but it's not reflecting immediately in the dataGrid or in any other cmp, (but OK in the database), then you might have called load.store() too early... before the SYNC's update/create was executed at the backend. When you say:
store.sync();
store.load();
The console.log will say sometimes that sync happens before load.... sometimes it will tell that load happens before sync... depending on which one finished first
I've seen a post here where SYNC was overriden: to give a callback function, haven't tried it though:
http://www.sencha.com/forum/showthread.php?136183-How-to-get-a-callback-from-store-sync
Right now, instead of a callback, I'm using the success method of Sync:
store.sync({
success: function(batch) {
console.log('The User Details was sync');
store.load();
}
});


Most of the time, I'm using the callback method of load.store(). This lessen headaches moving forward.