PDA

View Full Version : R/W from an Array ?



ushu
3 May 2010, 9:03 AM
Hi Gurus,

I have been playing for a few days with ExtJS3 and got stuck...
My problem is the following: I try to evaluate the possibility to add an ExtJs interface to an exisiting project (i.e. I have legacy JS code and server architecture I cannot modify). I have to display data in grid, and the data as an array of objects:



var myLegacyData = [
{ "Valuation Date" : "__date__:10 Apr 2010", "Payment Date" : "__date__:15 Apr 2010", "Coupon Level (%)" : 0.1},
{ "Valuation Date" : "__date__:20 Apr 2010", "Payment Date" : "__date__:25 Apr 2010", "Coupon Level (%)" : 0.1},
...
]
So my goal is to obtain an ExtJS GridPanel that:
- reads its rows from the array, using the appropriate converters (remove "__date__:" in front of dates, multiply the coupon level by 100 for display, etc.)
- write back to the array when the user modify a cell (using an inverse function)

note that i can not change the form of the array, as the rest of the JS code is not from me and still in devlopement.

I tried two approaches to overcome this issue:

1) use an ArrayStore



function convertDate(d) {
if (!d) return "";
d = d.substring(9);
return Date.parseDate(d, "d M Y");
}

function convertLevel(l) {
return l * 100.0;
}

var fields = [
{name: 'Valuation Date', mapping: 'Valuation Date', convert : convertDate, type: 'date' },
{name: 'Payment Date', mapping: 'Payment Date', convert : convertDate, type: 'date'},
{name: 'Coupon Level (%)', mapping: 'Coupon Level (%)', type: 'float' , convert: convertLevel, type: 'float' }
];

var store = new Ext.data.ArrayStore({
fields : fields
});
store.loadData(myLegacyData);


function itRenderer(val) {
return "<i>" + val + " </i>";
}

var cols = [
{ header: "Coupon Date", dataIndex: 'Valuation Date', editor : new Ext.form.DateField(), renderer: Ext.util.Format.dateRenderer('d M Y') },
{ header: "Payment Date", dataIndex: 'Payment Date', editor : new Ext.form.DateField(), renderer: Ext.util.Format.dateRenderer('d M Y') },
{ header: "Coupon Level (%)", dataIndex: 'Coupon Level (%)', editor : new Ext.form.TextField(), renderer: Ext.util.Format.numberRenderer('0.00') }
];

var editor = new Ext.grid.EditorGridPanel({
store: store,
columns: cols,
region: 'center'
});
(this code is simplified, there are actually more fields, but every ExtJS concept I used are in there)

My problem is: how do I write the "write" part : How do I serialize my Data back into my array ?

I could not figure a good answer, so I tried:

2) using a JsonStore:

the code is similar, but I had to use another object:



var dummyObject = { render: myLegacyData };
...
var store = new Ext.data.JsonStore({
fields: fields,
data: dummyObject,
root: 'render'
});
...
This approach has several flaw (imho):
- it does generate some more values (like the "successProperty", "totalProperty"...)
- I could not find a way to configure the JsonWriter to do what I wanted


all these experiments seem pretty strange to me: it was pretty obvious how to configure the reader part, using a bunch of callbacks. This part really rocks and the rendering is very nice.
But on the other hand, the "writer" part is somehow lacking (or so is my understanding of the framework,which is what I hope): why is there no ArrayWriter ? why doesn't the store have a "unconvert" or so method ?

If anyone has a solution to this problem, could you please give me a hint ?
I tried to be as descriptive as possible, hoping that it may help, and will be thankfull to any comment or answer.

Aurélien

PS: Please note that english is not my primery language, so there are probably many errors in this text. sorry...

wm003
3 May 2010, 10:47 PM
i guess the key here might be using the listener "afteredit" at the EditorGridPanel-Widget and modify the record as you desire



var my edgrid = new Ext.grid.EditorGridPanel({

listeners: {
afteredit: function(o) {
if (o.field == "Validation Date") {
o.record.set("Validation Date", "__date__"+o.record.get("Validation Date").format(d M Y));
}
}
}
});

ushu
5 May 2010, 6:30 AM
thanks a lot for the answer.

I tried to implement the modification you suggested, but had some problems with backward serialization:
- if I just add the listener as you settled, no modification is made on the data, and a small red triangle appears on top of the component
- I then tried to add a Ext.data.JsonWriter to the store, but it then complains about a missing proxy
- finally I added a Ext.data.DirectProxy to the store, but could not figure how to configure it:


var store = new Ext.data.JsonStore({
fields : fields,
root:'',
proxy: new Ext.data.DirectProxy(),
writer: new Ext.data.JsonWriter(),
autoSave: true
});
DirectProxy sounds like a good idea, as I don't want to modify the data. I could not figure out any working configuration: docs talk about giving urls to the 'api' option, but it is useless here as I want to perform a local update of my data...

Just to ensure I really understand how everything is tied together, here is how I understand the the communication among the framework:



+--------------------------------+ +------------------------+
| Store | | GridPanel |
| | | |
+--------+ Proxy +----------+ Reader | events +--------+ events | ??? | events +-----------+ |
| Server | <------> | RAW Data | -------> | --------- | Record | --------- | ------ | -------- | Component | |
+--------+ +----------+ <------- | +--------+ | | **** +-----------+ |
Writer +--------------------------------+ +------------------------+
your proposal is to plug into the events of the GridPanl (**** on my drawing), but wouldn't it be more natural to use a writer ? (if there is a way to specify a conversion function of course)
otherwise, what about the (before|after)write events of the store ?

here is the modified code, that does not work right now:


var myLegacyData = [
{ "Valuation Date" : "__date__:10 Apr 2010", "Payment Date" : "__date__:15 Apr 2010", "Coupon Level (%)" : 0.1},
{ "Valuation Date" : "__date__:20 Apr 2010", "Payment Date" : "__date__:25 Apr 2010", "Coupon Level (%)" : 0.1}
];
function convertDate(d) {
if (!d) return "";
d = d.substring(9);
return Date.parseDate(d, "d M Y");
}
function convertLevel(l) {
return l * 100.0;
}
var fields = [
{name: 'Valuation Date', mapping: 'Valuation Date', convert : convertDate, type: 'date' },
{name: 'Payment Date', mapping: 'Payment Date', convert : convertDate, type: 'date'},
{name: 'Coupon Level (%)', mapping: 'Coupon Level (%)', type: 'float' , convert: convertLevel, type: 'float' }
];
var store = new Ext.data.JsonStore({
fields : fields,
root:'',
proxy: new Ext.data.DirectProxy(),
writer: new Ext.data.JsonWriter(),
autoSave: true
});
store.loadData(myLegacyData);
var cols = [
{ header: "Coupon Date", dataIndex: 'Valuation Date', editor : new Ext.form.DateField(), renderer: Ext.util.Format.dateRenderer('d M Y') },
{ header: "Payment Date", dataIndex: 'Payment Date', editor : new Ext.form.DateField(), renderer: Ext.util.Format.dateRenderer('d M Y') },
{ header: "Coupon Level (%)", dataIndex: 'Coupon Level (%)', editor : new Ext.form.TextField(), renderer: Ext.util.Format.numberRenderer('0.00') }
];
var editor = new Ext.grid.EditorGridPanel({
store: store,
columns: cols,
region: 'center',
viewConfig: {
autoFill: true,
forceFit: true
},
listeners: {
afteredit: function (o) {
if (o.field === "Valuation Date") {
o.record.set("Valuation Date", "__date__:" + o.record.get("Valuation Date").format("d M Y"));
} else if (o.field === "Payment Date") {
o.record.set("Payment Date", "__date__:" + o.record.get("Payment Date").format("d M Y"));
} else if (o.field === "Coupon Level (%)") {
o.record.set("Coupon Level (%)", parseInt(o.record.get("Coupon Level (%)")));
}
}
}
});
Aurélien