PDA

View Full Version : [FIXED] Ext.data.Store CRUD operations fail for remote store



logicseeds
26 Nov 2011, 4:22 AM
REQUIRED INFORMATION




Ext version tested:

Touch 2 dev-preview pr 1 and 2

Browser versions tested against:

Browserindependant

Description:

As i have not been able to locate any real documentation / examples for write-stores, example used as configuration reference is and Ext example, see http://cdn.sencha.io/ext-4.0.7-gpl/examples/writer/writer.js.
When ever a batch operation fires due to dirty / phantom items in a store, it breaks with 'not a function' exceptions on calls to create/update/destroy.

Steps to reproduce the problem:

iterate following for each C/U/D operation
load remote store
delete item
sync store

The result that was expected:

valid XHR sent to API listed urls

The result that occurs instead:

TypeError: Cannot call method 'create' of undefined
TypeError: Cannot call method 'update' of undefined
TypeError: Cannot call method 'destroy' of undefined

Test Case:






Ext.define("mS.Person", {
extend: 'Ext.data.Model',
fields: [ 'name', 'email' ],
proxy: {
type: 'ajax',
api: {
read: 'xhr/data.php',
create: 'xhr/crud_be.php?action=create',
destroy: 'xhr/crud_be.php?action=delete',
update: 'xhr/crud_be.php?action=update'
},
reader: {
type: 'json',
root: 'users'
},
writer: {
type: 'json',
writeAllFields: false,
root: 'data',
allowSingle: false


}
}
});
Ext.define("mS.AjaxWriter", {
extend: "Ext.data.Store",
model: 'mS.Person'
})
Ext.define("mS.FormView", {
extend: 'Ext.form.Panel',
config: {
standardSubmit: false,
items : [{
xtype: 'fieldset',
id: 'anyFormFieldset',
items: [
{ xtype: 'textfield', label: 'name', name: 'name'},
{ xtype: 'emailfield', label: 'email', name: 'email'}
]
}, {
html: 'Commands output',
id: 'logout'
}]
},
constructor: function(config) {
this.callParent(arguments);


},
log: function(msg) {
this.down("#logout").innerElement.dom.innerHTML += "
" + msg
}


})
Ext.onReady(function() {
var formstore
Ext.create("mS.FormView", {
renderTo: Ext.getBody(),
unittest: function() {
this.log("testing...");
var item = formstore.getAt(0);
this.log("storeitem 0, dirty: " + item.dirty + " valid: " + item.isValid()+ " phantom: " + item.phantom)
this.log("manipulating item - item.set('name'', 'bo'')");
item.set("name", "bo");
this.log("storeitem 0, dirty: " + item.dirty + " valid: " + item.isValid() + " phantom: " + item.phantom)
this.log("Expected, dirty YES, phantom NO, valid YES")
this.log("store updaterecords count: " + formstore.getUpdatedRecords().length)

try {
formstore.sync()
} catch(e) {
this.log("on sync: " + e.toString())
}


formstore.removeAt(0);
this.log("record #0 deleted from store")
this.log("store deleterecords count: " + formstore.getRemovedRecords().length)


try {
formstore.sync()
} catch(e) {
this.log("on sync: " + e.toString())
}


this.log("creating record")
formstore.add( {name: 'claus', email: 'somemail@fab.org'} );
this.log("store newrecords count: " + formstore.getNewRecords().length)


try {
formstore.sync()
} catch(e) {
this.log("on sync: " + e.toString())
}
},
initialize: function() {
var me = this
formstore = Ext.create("mS.AjaxWriter");
formstore.load({
callback: function(records, loadOpt, success) {
if(success) {
me.load(records[0])
me.log('record #0 loaded from ' + records.length + " totalCount")
}
me.unittest();
}
});


}
})
})



HELPFUL INFORMATION




Screenshot or Video:

http://www.4shared.com/get/HktvSQTC/out.html
lossy quality preview: http://www.4shared.com/video/HktvSQTC/out.html

Debugging already done:

Commands output
record #0 loaded from 2 totalCount
testing...
storeitem 0, dirty: false valid: true phantom: false
manipulating item - item.set('name'', 'bo'')
storeitem 0, dirty: true valid: true phantom: false
Expected, dirty YES, phantom NO, valid YES
store updaterecords count: 1
on sync: TypeError: Cannot call method 'update' of undefined
record #0 deleted from store
store deleterecords count: 1
on sync: TypeError: Cannot call method 'destroy' of undefined
creating record
store newrecords count: 1
on sync: TypeError: Cannot call method 'create' of undefined

Possible fix:

problem resides in config { } migration?

Operating System:

Platform independant (linux)

logicseeds
26 Nov 2011, 7:04 AM
Possible fix:

problem resides in config { } migration?

As expected, create/destroy/update functions are actually available in the proxy. However after overriding a few of the function calls, allowing me to take a closer look - I have located the issue!

Essential codeblock resides in Ext.data.proxy.Proxy.prototype.batch:
(pr1) /src/data/proxy/Proxy.js:298


batch = Ext.create('Ext.data.Batch', {
proxy: me,
listeners: listeners || {}
}),

Problem is proxy config parameter is not set in the Ext.data.Batch.construct. Following does NOT help:


batch = Ext.create('Ext.data.Batch', {
config: { proxy: me },
listeners: listeners || {}
}),


Considering a store declaration, I ended up fixing it by overriding the store.proxy.batch method and substituting the batch instantiation with a custom Ext.data.Batch class (where construct references correctly):


Ext.define(AppName+".store.AnyFormExampleStore", {
extend: AppName + ".anyform.Store",
model: AppName + '.model.AnyFormExampleModel',

/* required config */
proxy: {
type: 'ajax',
api: {
read: 'xhr/data.php',
create: 'xhr/crudlink.php?task=create',
destroy: 'xhr/crudlink.php?task=delete',
update: 'xhr/crudlink.php?task=update'
},


reader: {
type: 'json',
root: 'users'
},
writer: {
type: 'json',
writeAllFields: false,
root: 'users',
allowSingle: false


},
batch: function(operations, listeners) {
var me = this,

batch = Ext.create('myBatch', {
proxy: me,
listeners: listeners || {}
}),
// batch = Ext.create('Ext.data.Batch', {
// config: { proxy: me },
// listeners: listeners || {}
// }),
useBatch = me.batchActions,
records;


Ext.each(me.batchOrder.split(','), function(action) {
records = operations[action];
if (records) {
if (useBatch) {
batch.add(Ext.create('Ext.data.Operation', {
action: action,
records: records
}));
} else {
Ext.each(records, function(record) {
batch.add(Ext.create('Ext.data.Operation', {
action : action,
records: [record]
}));
});
}
}
}, me);


batch.start();
return batch;
}
}
} );


Ext.define('myBatch', {
extend: 'Ext.data.Batch',
constructor: function(config) {
this.proxy = config.proxy;
this.callParent(arguments);
}
});

Jamie Avins
28 Nov 2011, 10:00 AM
Thank you for the report.

TommyMaintz
16 Dec 2011, 12:35 PM
Just wanted to give you a heads up on this issue. We are currently working on this and hope to get this fixed as part of the next Touch 2.0 release.

logicseeds
19 Dec 2011, 4:16 AM
good to know thx for the replies :)

TommyMaintz
16 Jan 2012, 2:38 PM
This has been fixed as part of the next Touch 2.0 release. If the problem still persists afterwards, please let us know. Thanks for the very detailed report, it was very helpful.