问题
I have two data models: Writer.AttributValeur
and Writer.Produit
.
Writer.Produit
has HasMany
/ BelongsTo
relationship with Writer.AttributValeur
.
Thus the definition is like this:
Ext.define('Writer.AttributValeur', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'int',
useNull: true
},
'description',
'val'
],
belongsTo: 'Writer.Produit'
});
Ext.define('Writer.Produit', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'int',
useNull: true
},
'titre',
'description'
],
hasMany: {
model: 'Writer.AttributValeur',
name: 'attributs'
}
});
var store = Ext.create('Ext.data.Store', {
model: 'Writer.Produit',
autoLoad: true,
autoSync: true,
proxy: {
type: 'ajax',
api: {
read: 'json/liste_view/',
create: 'json/item/?mode=create',
update: 'json/item/?mode=update',
destroy: 'json/item/?mode=destroy'
},
reader: {
type: 'json',
successProperty: 'success',
root: 'data',
messageProperty: 'message'
},
writer: {
type: 'json',
writeAllFields: true,
root: 'data'
}
}
});
Now, when I read the file, asking for "Produits", there's an AJAX answer that works perfectly:

And in each "row", there are many Writer.AttributValeur
(I've aliased them as "attributs" see picture):

The problem is when I insert a Writer.AttributValeur
in this "attributs
" field, like this:
form.getRecord().attributs().add(newrecord);
It works perfectly but when I call store.sync()
nothing happens. So I mark by hand the record as dirty
:
form.getRecord().attributs().add(newrecord);
form.getRecord().setDirty();
form.getRecord().store.sync();
Now it's sent, but the attributs
are not sent! See:

How shall I do to "add" this into the update process?
回答1:
Here's the override stuff:
Ext.data.writer.Json.override({
{*/*
* This function overrides the default implementation of
* json writer. Any hasMany relationships will be submitted
* as nested objects
*/*}
getRecordData: function(record) {
var me = this, i, association, childStore, data = {};
data = me.callParent([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) {
//Recursively get the record data for children (depth first)
var childData = this.getRecordData.call(this, childRecord);
if (childRecord.dirty | childRecord.phantom | (childData != null)){
data[association.name].push(childData);
record.setDirty();
}
}, me);
}
}
return data;
}
});
And here's an example of how I'm using it:
var store = Ext.create('Ext.data.Store', {
model: 'Writer.Produit',
autoLoad: true,
autoSync: true,
proxy: {
type: 'ajax',
api: {
read: 'json/liste_view/',
create: 'json/item/?mode=create',
update: 'json/item/?mode=update',
destroy: 'json/item/?mode=destroy'
},
reader: {
type: 'json',
successProperty: 'success',
root: 'data',
messageProperty: 'message'
},
writer: new Ext.data.writer.Json( {
type: 'json',
writeAllFields: true,
root: 'data'
})
}
});
And when I add a nested record here's how I do this with attributs
which is oneToMany association (see my question). It's important to note that I set Dirty all nested records so that I'm sure they're sent:
var rec = this.formDst.getRecord(),
atts = rec.attributs();
atts.add(sel);
for (var i = 0; i <atts.data.items.length; i++) {
atts.data.items[i].setDirty();
};
rec.setDirty();
rec.store.sync();
this.close();
回答2:
i liked the simple solution so i also added belongsTo Support:
Ext.data.writer.Json.override({
getRecordData:function (record) {
var me = this, i, association, childStore, data = {};
data = me.callParent([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) {
//Recursively get the record data for children (depth first)
var childData = this.getRecordData.call(this, childRecord);
if (childRecord.dirty | childRecord.phantom | (childData != null)) {
data[association.name].push(childData);
record.setDirty();
}
}, me);
}
if(association.type == 'belongsTo') {
// we need ucfirst
var method = 'get' + association.name.charAt(0).toUpperCase() + association.name.slice(1);
var childRecord = eval('record.' + method + '()');
var childData = this.getRecordData.call(this, childRecord);
if (childRecord.dirty | childRecord.phantom | (childData != null)) {
data[association.name] = childData;
record.setDirty();
}
}
}
return data;
}
});
回答3:
From the sencha docs - looks like you need to call sync on form.getRecord().attributs()
and not on the main record. Can you try that?
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.HasManyAssociation
回答4:
This feature is not supported in 4.0x and is not yet on the feature path for 4.1 as far as I know. There have been some attempts at resolution however, see this thread: http://www.sencha.com/forum/showthread.php?141957-Saving-objects-that-are-linked-hasMany-relation-with-a-single-Store
Also another interesting approach with forms: https://stackoverflow.com/a/9891694/834424 by Jamie Sutherland
来源:https://stackoverflow.com/questions/9871440/extjs-store-hasmany-belongsto-and-update-process-howto