PDA

View Full Version : [CLOSED] [#610] getRowsValues and prepareRecord - an option to ignore field's SubmitEmptyValue?



anup
Dec 12, 2014, 11:42 AM
Hi,

I notice that in the store's JavaScript prepareRecord method, towards the very end it does this:



for (var k in data) {
field = this.getFieldByName(k);

if (Ext.isEmpty(data[k], false) && this.isSimpleField(k, field)) {
switch (field.submitEmptyValue) {
case "null":
data[k] = null;
break;
case "emptystring":
data[k] = "";
break;
default:
delete data[k];
break;
}
}
}


In my particular scenario I sometimes do not want the default switch to fire (to delete the property). But other times I do.

My particular example:
- I have an editable grid which has a lot of columns.
- When I save edits, the data sent back to the server is very lean: only modified fields are sent back
- In another case, I use grid.getRowsValues({ visibleOnly: true }) to pre-process data before using it to generate CSV for the page.
- But in this case, some empty cells are not returned because their SubmitEmptyValue property is not defined and therefore gets deleted

The problem I have is that I don't have a way to ignore the submitEmptyValues configuration without a trade-off:

My current workaround is to set submitEmptyValue to null or empty string for my various fields so they are not deleted for the export scenario. But that means my main use case (saving edits) has more data to transfer than my secondary use case (export to CSV).

The other tricky things is for my CSV scenario I try to create an initial row of headers based on visible header columns. But I run into an issue where even though I get all the right headers, each row may not end up having all the data because the submitEmptyValues is undefined for some fields resulting in rows mismatching and not aligning with the column headers.

Hence, I'd like to request a new configuration property to optionally by-pass the above switch statement would help preserve the leaner save scenario while supporting the secondary export to CSV. (For backward compatibility the property would default such that today's behaviour is the default, so I would explicitly need to make use of this new property myself, once available.)

Would this be possible?

If you agree, this is also the exact same issue I face in Ext.NET 1.x - I think the code is virtually the same in this area. Could it also be applied to 1.x? (I have not checked 3.x but maybe it needs to be applied there, too?)

Many thanks!

Daniil
Dec 12, 2014, 9:14 PM
Hi Anup,

Please correct if I misunderstand something.

App.GridPanel1.getRowsValues({ ingoreSubmitEmptyValue: true })

Override

Ext.data.Store.override({
prepareRecord: function (data, record, options, isNew) {
var newData = {},
field,
idProp = this.proxy && this.proxy.reader ? this.proxy.reader.getIdProperty() : "id";

if (options.filterRecord && options.filterRecord(record) === false) {
return;
}

if (options.visibleOnly && options.grid) {
var columns = options.grid.headerCt.getVisibleGridColumns(),
i, len;

for (i = 0, len = columns.length; i < len; i++) {
newData[columns[i].dataIndex] = data[columns[i].dataIndex];
}

data = newData;
}

if (options.dirtyRowsOnly && !isNew) {
if (!record.dirty) {
return;
}
}

if (options.dirtyCellsOnly === true && !isNew) {
newData = {};

for (var j in data) {
if (record.isModified(j)) {
newData[j] = data[j];
}
}

data = newData;
}

for (var k in data) {
if (options.filterField && options.filterField(record, k, data[k]) === false) {
delete data[k];
}
}

if (options.mappings !== false && this.saveMappings !== false) {
var m,
map = record.fields.map,
mappings = {};

Ext.iterate(data, function (prop, value) {
m = map[prop];

if (m) {
mappings[m.mapping ? m.mapping : m.name] = value;
}
});

if (options.excludeId !== true) {
if (record.phantom) {
if (record.clientIdProperty) {
mappings[record.clientIdProperty] = record.internalId;
}
} else {
mappings[idProp] = record.getId();
}
}

data = mappings;
}

if (!options.ingoreSubmitEmptyValue) { // added
for (var k in data) {
field = this.getFieldByName(k);

if (Ext.isEmpty(data[k], false) && this.isSimpleField(k, field)) {
switch (field.submitEmptyValue) {
case "null":
data[k] = null;
break;
case "emptystring":
data[k] = "";
break;
default:
delete data[k];
break;
}
}
}
}

if (options.prepare) {
options.prepare(data, record);
}

return data;
}
});

anup
Dec 15, 2014, 8:25 AM
Hi,

Yes, that is what I am looking for :)

Thanks!

anup
Dec 16, 2014, 9:30 AM
By the way, just wanted to double check: was your suggestion something I should apply myself, or something you were thinking of applying to your code base but just double checking first?

If it was the latter, I just noticed a small typo in the property name: "ingoreSubmitEmptyValue". It should start with "ign" instead of "ing" :)

Also, if you are going to apply this to your code base, is it something you would consider putting in 1.x as well, or should I do the override myself for 1.x?

Finally, if it is something I need to override myself (in 1.x and/or 2.x) perhaps it is possible to factor out that switch part into its own method (passing in the options etc) so I only have to override that part, not the entire logic?

Thanks!

Daniil
Dec 16, 2014, 10:30 AM
I just wanted your confirmation that it is indeed what you are looking for.

Also I waited when you spot the typo!:) Thank you.

I am going to add it for all - v1, v2 and v3.

anup
Dec 16, 2014, 10:43 AM
That's really appreciated. Thanks!

Daniil
Dec 16, 2014, 2:18 PM
v1: revision 6205
v2: revision 6206
v3: revision 6207

Thank you for the suggestion!

I am closing the thread, but please feel free to post any follow-up.

anup
Dec 16, 2014, 3:59 PM
Many thanks for this. Works for 1.x and 2.x (not tried 3.x but I presume it works there if it is the same logic).

Daniil
Dec 17, 2014, 5:21 AM
Thank you for confirming, much appreciated!