I have extended Ext.data.Operation
to implement a custom commitRecords
method.
The Ext.data.Operation
class is used for all communication between stores and their proxy.
The commitRecords
method specifically is used to update the data in a data store according to data returned from a proxy writer.
I can't seem to get a grip on how to set up my proxies to use my extended version of Ext.data.Operation
.
I've been rifling through the Ext.data.*
package but can't seem to find where the Ext.data.Operation
is created so I will know what class to tell to use this new extended Ext.data.Operation
class with the custom commitRecords
method.
Has anyone else extended this before, could give me some pointers?
I found it, the batch
method of Ext.data.Proxy
is where an Ext.data.Operation
object is created to send to the server.
I extended Ext.data.proxy.Ajax
with a new batch
method where I just switch out the new Ext.data.Operation
for my own Operation class.
EDIT
Only because you asked DmitryB. The short story about why I had to implement my own commitRecords method is that I needed my data models "internalId" fields to match the actual database record ID field. I won't go into why exactly, it's too convoluted for me to express, but here's what I did:
How I understand it, the commitRecords
method is fired as one of the last actions when calling store.sync()
it automatically replaces the dirty records on the client side with the new server side records as long as you write your server side controller to return the new server record in the Ajax response, it does this whenever the sync request does an insert or update.
The official implementation of commitRecords
tries to match this returned server record to the dirty client record by using the "internalId" field of the data model.
Obviously, I have no idea what the next incremental database ID is going to be for new records, so I cannot assign it on the client side as the ID before the record syncs with the database, therefore the server record will never match be able to match up against the dirty client record's internalId when commitRecords is called, i.e. the client record will not get the correct database ID, which I need.
So, because all of my writable data models for this app have a "create_time" field I decided to make the commitRecords method match the server records with the client records using the "create_time" field instead of "internalId".
Here is the extended Ext.data.Operation class, where I did this:
Ext.define('MyApp.ux.QueryOperation', {
extend: 'Ext.data.Operation',
/**
* Use the date_created timestamp if we cant match to an ID.
* This allows client records that did not previously exist on the server
* to be updated with the correct server ID and data
* NB: All implementing data models require a "date_created" field.
*/
commitRecords: function (serverRecords) {
var me = this,
mc, index, clientRecords, serverRec, clientRec;
if (!me.actionSkipSyncRe.test(me.action)) {
clientRecords = me.records;
if (clientRecords && clientRecords.length) {
if (clientRecords.length > 1) {
mc = new Ext.util.MixedCollection();
mc.addAll(serverRecords);
Ext.each(clientRecords, function(clientRec) {
serverRec = mc.findBy(function(record) {
var clientId = clientRec.getId(),
clientTime = clientRec.get('date_created').getTime(),
serverTime = record.get('date_created').getTime();
if(clientId && record.getId() === clientId) {
return true;
}
// timestamp can be within 2ms of record
// (it seems to change slightly in serialization)
return (clientTime > serverTime - 2 && clientTime < serverTime + 2);
});
me.updateClientRecord(clientRec, serverRec);
});
} else {
clientRec = clientRecords[0];
serverRec = serverRecords[0];
me.updateClientRecord(clientRec, serverRec);
}
if (me.actionCommitRecordsRe.test(me.action)) {
for (index = clientRecords.length; index--; ) {
clientRecords[index].commit();
}
}
}
}
},
});
As I mentioned in the answer, I found that I had to extend proxy to make use of my new Operation class. The only thing I extended was the batch
method, replacing only two lines in the method which said new Ext.data.Operation
to now say new MyApp.ux.QueryOperation
(my new Operation class above). This then called my own commitRecords method when a response came back from the server. I also gave the extended proxy an alias "proxy.query" so that I could tell my stores to use it like this:
Ext.define('MyApp.store.MyStore', {
extend: 'Ext.data.Store',
requires: [
'ST.ux.QueryProxy',
],
title: 'Student',
model: 'MyApp.model.MyModel',
proxy: {
type: 'query',
// ... ^^^^^ uses my QueryProxy now
// other configs...
}
});
(If it seems like I am going about this wrong way or missed something in the docs, please let me know. I would be happier with a built in method of achieving this functionality.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With