That won't do, as the nameProperty field will only except one level. So
It will change {AutoUsers:} to: {Auto.users:} for example, but not to: {auto: {users:}}
That won't do, as the nameProperty field will only except one level. So
It will change {AutoUsers:} to: {Auto.users:} for example, but not to: {auto: {users:}}
Sorry for necro-ing this thread, but I hope this might be handy for anyone trying to safe a hasMany relation. I have made some adjustments to the code of @olivierpons. His code didn't work for me and I do not want to check for modified records but want to send everything. Code below was tested against 4.1.1
Code:var ExtDataWriterJsonOriginal_getRecordData = Ext.data.writer.Json.prototype.getRecordData; Ext.data.writer.Json.override({ getRecordData: function(record) { var me = this, i, association, childStore, data = {}; data = ExtDataWriterJsonOriginal_getRecordData(record); /* Iterate over all the hasMany associations */ for (i = 0; i < record.associations.length; i++) { association = record.associations.get(i); if (association.type == 'hasMany') { data[association.name] = []; childStore = eval('record.'+association.name+'()'); //Iterate over all the children in the current association childStore.each(function(childRecord) { data[association.name].push(childRecord.getData()); }, me); } } return data; } });
Thank you very much for following this, I have small problems with grids, I suppose it has something to do with my code, so I'll try yours and if things come better I'll let you know
Olivier Pons
I have updated the code so that it overrides as encouraged by Sencha and so that it still sends all fields, even those unchanged, which the previous version didn't (for some reason)
Code:Ext.override(Ext.data.writer.Json, { getRecordData: function(record) { var me = this, i, association, childStore, data = this.callParent(arguments); /* Iterate over all the hasMany associations */ for (i = 0; i < record.associations.length; i++) { association = record.associations.get(i); if (association.type == 'hasMany') { data[association.name] = []; childStore = eval('record.'+association.name+'()'); //Iterate over all the children in the current association childStore.each(function(childRecord) { data[association.name].push(childRecord.getData()); }, me); } } return data; } });
I landed here because I had this problem in Sencha Touch. Here's the code ported over to Touch-friendliness (2.0.1.1), for anyone interested.
Code:Ext.define('Ext.data.writer.override.Json', { override: 'Ext.data.writer.Json', getRecordData: function(record) { var me = this, i, association, type, key, store, childData, data = this.callParent(arguments), associations = typeof record.getAssociations === 'function' ? record.getAssociations() : []; for (i = 0; i < associations.length; i++){ association = associations.get(i); type = association.getType(); key = association.getAssociationKey(); if (type.toLowerCase() == 'hasmany'){ store = record[association.getName()](); if(store && store.getCount() > 0){ //Nest all of the store items. data[key] = []; store.each(function(childRecord) { data[key].push(childRecord.getData()); }, me); } //If the store is empty and the key already exists with items, make it an empty array. else if(data[key] && data[key].length){ data[key] = []; } } } return data; } });
Last edited by stephenr85; 5 Oct 2012 at 11:21 AM. Reason: removed logging from code
This code gets not called when only the associated data has been updated for a given record since Ext.data.Store.sync() will not find anything to update.
I used the code from flanders. It works only if the data of the main model is changed. If I only change the associated data, I need to call manually
Has anyone a solution for that?Code:record.dirt=true; store.sync();
Thx Mike
Have you explored the source? If you step through the call through sync() you can most likely see how it is determined which records are dirty. If you can override this method with an extra hook to check for changed parts your done.
Thx flanders.
I write two functions for the store to check all associations too
Now I just have to callCode:Ext.override(Ext.data.Store, { filterNew:function(record) { var me = this, i, association, childStore, childRecordPhantom=false; if( record.phantom === false && record.associations.length ) { for (i = 0; i < record.associations.length; i++) { association = record.associations.get(i); if (association.type == 'hasMany') { childStore = eval('record.'+association.name+'()'); childStore.each(function(childRecord) { childRecordPhantom = childRecord.phantom === true && childRecord.isValid(); if( childRecordPhantom ) { return false; } }, me); if( childRecordPhantom ) { break; } } } } return childRecordPhantom || record.phantom === true && record.isValid(); }, filterUpdated: function(record) { var me = this, i, association, childStore, childRecordDirty=false; if( record.dirty === false && record.phantom === false && record.associations.length ) { for (i = 0; i < record.associations.length; i++) { association = record.associations.get(i); if (association.type == 'hasMany') { childStore = eval('record.'+association.name+'()'); childStore.each(function(childRecord) { childRecordDirty = childRecord.dirty === true && childRecord.phantom !== true && childRecord.isValid(); if( childRecordDirty ) { return false; } }, me); if( childRecordDirty ) { break; } } } } return childRecordDirty || record.dirty === true && record.phantom !== true && record.isValid(); } });
But I cant find a way to use autostore on the master models store, so I only need to modfiy child model data. Have you another hint for me?Code:store.sync();
I find a function "afterEdit" on the model which fires the "afterEdit" event on the associated store, but this needs to bubble up to the master model store. I dont know how this can be done.
Thx Mike
How about looking for the code that creates the childStore? At that point, you can add an afteredit listener to that store I think?