PDA

View Full Version : store: getById fails after record creation



callipigia
3 Aug 2010, 2:22 AM
searching the forum i found a similar topic, however I couldn't fix the problem by that, so I try to explain what is going on in my case.

I set up a store which handles record operations server side. All operations seem to work correctly but creation:



record = new gecalPdlFiltroStore.recordType({
ANNO_RIF_INIZIO: anno_rif_inizio,
ANNO_RIF_FINE: anno_rif_fine,
DESCRIZIONE: descrizione,
PREDEFINITO: predefinito,
AREE: aree,
UFFICI: uffici
});
gecalPdlFiltroStore.add(record);
gecalPdlFiltroStore.save();


the store has autoload and autosave = false.

New records are correctly added (I see them server side and client side, in the store), but the getById method always fails. Here are some things I noticed inspecting runtime data:

- new record has the id property correctly set (the one which comes out of the server)
- new record has a _phid generated by extjs framework (existing records don't have it)
- new record and existing ones have dirty, editing, phantom = false, modfied=null
- new record doesn't have json property but holds data property correctly populated
- store.totalLength is 1 unit shorten then store.data.length; so it's likely store holds up whole data but it doesn't "recognize" it

so far I tried to:

- call store.load({add: true})
- call store.commitChanges after each operation

thanks for any help

Condor
3 Aug 2010, 2:37 AM
Are you saving a single record or multiple records (Ext currently has a bug in remapping multiple records)?

callipigia
3 Aug 2010, 3:12 AM
single record; I'm now using extjs 3.2.1...so maybe this post has to be moved under a diffent forum

thx

callipigia
3 Aug 2010, 3:46 AM
although getById doesn't work findExact does:



var r = gecalPdlFiltroStore.getAt(gecalPdlFiltroStore.findExact(gecalPdlFiltroStore.reader.meta.idProperty, id))


where id holds the id value of the added record (or updated one).

So i could use findExact, but I'm not sure that's the correct workaround...

Condor
3 Aug 2010, 4:18 AM
The record id and a field that holds the id are two completely different things.

Try this:

var r = gecalPdlFiltroStore.getAt(gecalPdlFiltroStore.findExact(gecalPdlFiltroStore.reader.meta.idProperty, id));
alert(r.id == id);

callipigia
3 Aug 2010, 4:37 AM
alert(r.id == id) is true

Condor
3 Aug 2010, 5:55 AM
Then the only explanation can be that the reMap() failed (which is obvious because _phid still exists).

Is your server returning the created record as a single object or as an array of one object (Ext has a bug when processing arrays).

netsuo
3 Aug 2010, 6:03 AM
It seems to be the same problem I had..
Condor, are you sure that it's only with multiple records ? Because I *NEVER* allow user to insert multiples records but I *always" have the problem.

I'm reposting my workaround (as it seems to do the trick before an official bugfix):


Ext.override(Ext.data.DataReader,
{
realize: function(rs, data){
if (Ext.isArray(rs)) {
for (var i = rs.length - 1; i >= 0; i--) {
// recurse
if (Ext.isArray(data)) {
this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());
}
else {
// weird...rs is an array but data isn't?? recurse but just send in the whole invalid data object.
// the else clause below will detect !this.isData and throw exception.
this.realize(rs.splice(i,1).shift(), data);
}
}
}
else {
// If rs is NOT an array but data IS, see if data contains just 1 record. If so extract it and carry on.
if (Ext.isArray(data) && data.length == 1) {
data = data.shift();
}
if (!this.isData(data)) {
// TODO: Let exception-handler choose to commit or not rather than blindly rs.commit() here.
//rs.commit();
throw new Ext.data.DataReader.Error('realize', rs);
}
rs.phantom = false; // <-- That's what it's all about
rs._phid = rs.id; // <-- copy phantom-id -> _phid, so we can remap in Store#onCreateRecords
rs.id = this.getId(data);
rs.data = data;

var map = rs.store.data.map[rs._phid];
rs.store.data.map[rs.id] = map;
delete rs.store.data.map[rs._phid];
rs.commit();
}
}
});



EDIT: nevermind about my question Condor, I didn't read your last answer. I'm returning the record as an array even if it is the only one, it explains my problem.

Condor
3 Aug 2010, 6:16 AM
Link to bugreport (http://www.sencha.com/forum/showthread.php?105442-3.2-OPEN-1158-DataReader.onCreateRecords-doesn-t-reMap-for-mutiple-records).

mszwarc
23 Nov 2010, 5:58 AM
Small fix to fix ;-)

Ext.override(Ext.data.JsonReader,
{
realize: function(rs, data){
if (Ext.isArray(rs)) {
for (var i = rs.length - 1; i >= 0; i--) {
// recurse
if (Ext.isArray(data)) {
this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());
}
else {
// weird...rs is an array but data isn't?? recurse but just send in the whole invalid data object.
// the else clause below will detect !this.isData and throw exception.
this.realize(rs.splice(i,1).shift(), data);
}
}
}
else {
// If rs is NOT an array but data IS, see if data contains just 1 record. If so extract it and carry on.
if (Ext.isArray(data) && data.length == 1) {
data = data.shift();
}
if (!this.isData(data)) {
// TODO: Let exception-handler choose to commit or not rather than blindly rs.commit() here.
//rs.commit();
throw new Ext.data.JsonReader.Error('realize', rs);
}
rs.phantom = false; // <-- That's what it's all about
rs._phid = rs.id; // <-- copy phantom-id -> _phid, so we can remap in Store#onCreateRecords
rs.id = this.getId(data);
rs.data = data;

var map = rs.store.data.map[rs._phid];
// update keys array (bug with selection)
for(var i=0; i<rs.store.data.keys.length; i++) {
if (rs.store.data.keys[i] == rs._phid) {
rs.store.data.keys[i] = map.id;
break;
}
}
rs.store.data.map[rs.id] = map;
delete rs.store.data.map[rs._phid];
rs.commit();
}
}
});

update a keys array in store (selection bug)

jwcraig
24 Nov 2010, 1:16 PM
Small fix to fix ;-)

Thanks mszwarc, this workaround solved my problem.