PDA

View Full Version : JsonReader: how to read arrays of arrays



pbesi
7 Sep 2010, 4:53 AM
Hello. I want to write JSON data coming from the server in a extjs grid.
My Jsonreader is:


var reader = new Ext.data.JsonReader( {
idProperty: 'idAuthor',
fields: [
{name: 'firstName'},
{name: 'lastName'},
{name: 'documents'}
]
});


and the columns definition in my grid panel is:


columns:[
{
header: "Firstname",
dataIndex: 'firstName',
width: 120
},{
header: "Lastname",
dataIndex: 'lastName'
},{
header: "Document version",
dataIndex: 'documents'
}],



My problem is that "documents" is not a primitive data like a string, but an array, inside I can find document version, date, etc. I need to extract these data and to put them in the grid columns.

Running the code, I can see the columns firstname, lastname but about documents, I get the string "[object Object]".

If I want to extract the string "docversion" from documents, normally I can write documents["docversion"] or if I know the index, I can write documents[4] if "4" is the right index.

In my jsonreader, I tried both "{name: documents["docversion"]}" and {name: documents[4]}" without success.
Can anyone write me how to extract the data inside "documents"?

More in general, how can I extract with jsonreader, the "docversion" from the following JSON data


author:{firstname:"aa", lastname:"bb", documents:[{docversion:"1", date:"..."},{docversion:"1",...}]}

Thank you
Pbesi

steffenk
7 Sep 2010, 5:01 AM
name: 'documentVersion', mapping: documents.docversion

etc

Condor
7 Sep 2010, 5:02 AM
But you have multiple documents, so also multiple versions!

What should the "Document version" column display?

If you want to follow @steffenk's method then it would be:

{name: 'documentVersion', mapping: 'documents[0].docversion'}
But I think using a column renderer would probably be better.

pbesi
7 Sep 2010, 6:04 AM
Thank you Steffenk and Condor. Unfortunately it answers "documents is not defined"!! But I if see the json data, "documents" exists and contain several data. Here my json data:



[
{
documents:[
{
docversion:"1",
idDocument:1,
insertdate:Mon Sep 06 2010 17:16:38 GMT+0200 (ora legale Europa occidentale),
pathfile:"C:\archivio\storia.txt",
pubblicationdate:Wed Dec 13 2006 00:00:00 GMT+0100 (ora solare Europa occidentale),
title:"Storia"
}
],
firstName:"Mario",
idAuthor:1,
lastName:"Rossi"
},
{
documents:[
{
docversion:"1",
idDocument:4,
insertdate:Mon Sep 06 2010 17:16:38 GMT+0200 (ora legale Europa occidentale),
pathfile:"C:\archivio\chimica.doc",
pubblicationdate:Thu Sep 20 2007 00:00:00 GMT+0200 (ora legale Europa occidentale),
title:"La chimica moderna"
},
{
docversion:"1",
idDocument:2,
insertdate:Mon Sep 06 2010 17:16:38 GMT+0200 (ora legale Europa occidentale),
pathfile:"C:\archivio\manuale del fai da te.txt",
pubblicationdate:Tue Dec 12 2006 00:00:00 GMT+0100 (ora solare Europa occidentale),
title:"Manuale del fai da te"
},
{
docversion:"1",
idDocument:3,
insertdate:Mon Sep 06 2010 17:16:38 GMT+0200 (ora legale Europa occidentale),
pathfile:"C:\archivio\biologia I.pdf",
pubblicationdate:Thu Sep 09 2010 00:00:00 GMT+0200 (ora legale Europa occidentale),
title:"Biologia"
}
],
firstName:"Gino",
idAuthor:2,
lastName:"Bianchi"
},
{
documents:[
.......


My intention is to get all the data inside "documents". Please do you have any other suggestion?
I didn't make a "root" json data, could that be a problem?
Thank you
Pbesi

Condor
7 Sep 2010, 6:20 AM
Forgot the quotes:

{name: 'documentVersion', mapping: 'documents[0].docversion'}

pbesi
7 Sep 2010, 7:58 AM
Hello Condor,
no way, I also tried putting quotes, but the I got an empty column. This happens if I write "{name: 'docVersion', mapping: 'documents.docversion', type:'auto'}.

If I write {name: 'docVersion', mapping: 'documents[0].docversion', type:'auto'}, also the firstname and lastname columns are empty. I don't get any message error, also using firebug.

I really don't know why it doesn't work!
Pbesi

pbesi
7 Sep 2010, 11:18 AM
Hello, ok problem solved.
The syntax {name: 'docVersion', mapping: 'documents[0].docversion]} is correct.
The problem was due to the fact that some records have an empty documents array, in my case it is possible to have an author without any document. In my mind, for these authors, I was expecting a document version column with a blank field, while, from the jsonreader point of view, this is not possible. Probably, for those authors without documents, I need to fill "documents" with null values.

Thank you
Pbesi

Condor
7 Sep 2010, 10:28 PM
Or you could write a mapping function, e.g.

{name: 'docVersion', mapping: function(v){
return v.documents && v.documents.length ? v.documents[0].docversion : null;
}}

pbesi
10 Sep 2010, 5:38 AM
Yes, your suggestion in great. It works fine! Thank you. But unfortunately my problem is not totally solved. Because I've e one-to-may relation (one author with zero or more documents), my json data obviously have one author and an array of documents.
Instead, jsonreader is expecting one author (in my case the same for each record) and one document for each record (one-to-one), but this is not my data structure. Do I have to manage it in the server side or is there any ExtJs tool in order to manage such kind of data? My final grid should show an author and all the related documents, and not several records with the same author, one for each documents. Thank you.
Pbesi

mschwartz
10 Sep 2010, 5:49 AM
{
header: "Document version",
dataIndex: 'documents',
renderer: function(documents, p, r) {
return documents[whatever].whateverlse;
}
}

pbesi
10 Sep 2010, 7:08 AM
I'm sorry. My request is not clear because of my bad english! What I meant is that in my grid panel, I need to group all documents per author, something like

firstname1 lastname1 title_x docversion_x date_x
title_y docversion_y date_y
.................................

firstname2 lastname2 title_w docversion_w date_w
title_z docversion_z date_z
..................................

firstname3 lastname3 title_z docversion_z date_z
...................................

This data structure is the same you get from a SQL query if you have a one-to-may relation (one author, many documents)

From the ExtJs point of view, in order to group data, I know there exists GroupingStore. It gets the data from jsonreader. But both are expecting data like (for example for the first author):

firstname1 lastname1 title_x docversion_x date_x
firstname1 lastname1 title_y docversion_y date_y
firstname1 lastname1 title_z docversion_z date_z

In such manner I need to change the data coming from the server, because I need to repeat the same author for each document related to him. Is there an ExtJS trick in order to manage data coming from a one-to-many SQL query like the one described above? Thank you.
Pbesi

Condor
10 Sep 2010, 7:14 AM
You would need to flatten the data, e.g.

root: function(v){
var root = [], i, len = v.length, j, jlen, author;
for (i = 0; i < len; i++) {
author = v[i];
for (j = 0, jlen = author.documents.length; j < jlen; j++) {
Ext.apply(author.documents[i], author);
}
root.push.apply(root, author.documents);
}
return root;
},
fields: [
'firstName',
'idAuthor',
'lastName',
'docversion',
'idDocument',
'insertdate',
'pathfile',
'pubblicationdate',
'title'
]

pbesi
10 Sep 2010, 8:22 AM
Thank you Condor.
Now I wrote getRoot function in my JsonReader, but nothing has changed. Should my grid find the new root definition?
I also tried to insert an alert inside the function but I didn't get any alert windows, the new function has not been executed. Please be patient, I lost myself, reading the getRoot API documentation I just found "Abstract method created in extension's buildExtractors imp", mmmmhhh... not clear for me, I don't know what to do now with the new getRoot definition.
Thank you
Pbesi

Condor
10 Sep 2010, 11:11 AM
Sorry, that should have been 'root' and not 'getRoot'.