PDA

View Full Version : Unable to display json data in grid



mhuibers
8 Mar 2007, 2:32 AM
Hello,

Problem:
I am trying to load data from a returned Json string into a grid. The data is not displayed, however the grid and one empty row are displayed.

Used technologies:
Obviously yui-ext, AjaxPro2, newtonsoft.json and asp.net 2.0

Setup:
aspx.cs file containing following code


[AjaxMethod]
public string GetSomePersonObjects()
{
string result = JavaScriptConvert.SerializeObject(BusinessLayer.GetSomePersonObjects());
return result;
}

result:
[{\"Aliases\":\"alias1\",\"FirstName\":\"firstname1\",\"LastName\":\"lastname1\"},
{\"Aliases\":\"alias2\",\"FirstName\":\"firstname2\",\"LastName\":\"lastname2\"}]


javascript file containing following code

var InitPersonGrid =
{
init: function()
{
_Default.GetSomePersonObjects(getSomePersonObjects_callback);
}
};

function getSomePersonObjects_callback(data)
{
var personData=[data];

var persons = Ext.data.Record.create
([
{name: 'firstName', mapping: 'FirstName'},
{name: 'lastName', mapping: 'LastName'},
{name: 'aliases', mapping: 'Aliases'}
]);

var reader =new Ext.data.JsonReader
(
{
root: '',
id: 'firstName'
}, persons
);

var ds = new Ext.data.Store
({
proxy: new Ext.data.MemoryProxy(personData),
reader: reader,
remoteSort: true
});
ds.setDefaultSort('firstName', 'desc');

// Define columns for grid and link to datafield in dataset (dataIndex)
var cm = new Ext.grid.ColumnModel
([
{
header:'First Name',
dataIndex:'firstName'
},
{
header:'Last Name',
dataIndex:'lastName'
},
{
header:'Aliases',
dataIndex:'aliases'
}
]);

var grid1 = new Ext.grid.Grid('container',
{
ds: ds,
cm: cm,
selModel: new Ext.grid.RowSelectionModel({singleSelect:true}),
enableColLock:true
});

ds.load();
grid1.render();
grid1.getSelectionModel().selectFirstRow();
}
Ext.onReady(InitPersonGrid.init, InitPersonGrid, true);


Additional info:
Apparently I did something wrong ... i've noticed that the returned json containes escape characters. Also when i manually add a json string (without the escape characters '\') the grid does show data.


Hopefully someone can help me out.

Thanks in advance

Michiel

BernardChhun
8 Mar 2007, 4:50 AM
you need to have a root value in your jsonReader.

and the JSONified data returned should be in this structure:


{"yourRoot": [{\"Aliases\":\"alias1\",\"FirstName\":\"firstname1\",\"LastName\":\"lastname1\"},
{\"Aliases\":\"alias2\",\"FirstName\":\"firstname2\",\"LastName\":\"lastname2\"}]}

so both the root specified in your JsonReader and in the JSONified data has to be the same.

I'm impressed...Every newbie should report an error in the way you did!!! :wink:

mhuibers
8 Mar 2007, 5:05 AM
Many thanks for your reply BernardChhun,

I examined the JSONified data object and the data.json value is as follows:

"\"[{\\"Aliases\\":\\"alias1\\",\\"FirstName\\":\\"firstname1\\",\\\"LastName\\":\\"lastname1\\"}]\";/*"


The string i posted before is the result if you use the data object itself (as i did in my code).
However the result from data.json doesn't help me either. As i see from your example string there are quite a few differences between yours and what the newtonsoft.json.JavaScriptConvert.SerializeObject function returns. I tried to serialize using AjaxPro as well but it gives me a similar result.

Is the string as posted above incorrect? or do I need to manipulate the string before using it?

Thanks

Animal
8 Mar 2007, 5:20 AM
You don't have to have a root any more.

If you don't supply one, it's assumed that you have returned a data Array rather than an object with a designated "root" property which is a the data Array.

Animal
8 Mar 2007, 5:21 AM
Er, that's Rev 3 I mean....

@mhuibers. I think you have too may backslashes.

Is that from Firebug that you're copying the json data?

BernardChhun
8 Mar 2007, 5:29 AM
Many thanks for your reply BernardChhun,

I examined the JSONified data object and the data.json value is as follows:

"\"[{\\"Aliases\\":\\"alias1\\",\\"FirstName\\":\\"firstname1\\",\\\"LastName\\":\\"lastname1\\"}]\";/*"


The string i posted before is the result if you use the data object itself (as i did in my code).
However the result from data.json doesn't help me either. As i see from your example string there are quite a few differences between yours and what the newtonsoft.json.JavaScriptConvert.SerializeObject function returns. I tried to serialize using AjaxPro as well but it gives me a similar result.

Is the string as posted above incorrect? or do I need to manipulate the string before using it?

Thanks

it seems there are too many \ to me here! If we take a look at the newtonSoft JSON sample here : http://www.newtonsoft.com/products/json/

it seems your data is corrupted somehow...how does it look before you JSON it? If you use the same data as on the example...does it return the same data?

mhuibers
8 Mar 2007, 5:33 AM
Its coming from vs.net 2005 IDE. I examined the 'data' object in the quick watch/watch windows.

If I output data.json with document.write(data.json) the result is this:

"[{\"Aliases\":\"alias1\",\"FirstName\":\"firstname1\",\"LastName\":\"lastname1\"}]\";/*"


If I output data.value with document.write(data.value) the result is:

[{"Aliases":"alias1","FirstName":"firstname1","LastName":"lastname1"}]

However both do not seem to work.

mhuibers
8 Mar 2007, 5:44 AM
BernardChhun,

The example from newsoft has the following output

document.write(data.json):
"{\"Name\":\"Apple\",\"Expiry\":new Date(1230422400000),\"Price\":3.99,\"Sizes\":[\"Small\",\"Medium\",\"Large\"]}";/*


document.write(data.value):
{"Name":"Apple","Expiry":new Date(1230422400000),"Price":3.99,"Sizes":["Small","Medium","Large"]}

mhuibers
8 Mar 2007, 5:47 AM
Maybe there is some more explanation to do on my side:

The function GetSomePersons return a generic collection class that implements:
IBindingList, IComponent, IDisposable,IList

This collection class marked as serializable and obviously contains the objects that I am interested in.

BernardChhun
8 Mar 2007, 5:50 AM
very deeply strange...

here's a screenshot of what I get from our server to populate the grid. That is the good old .33 one but the JSON data is similar.

http://i17.tinypic.com/48p1g7b.png

as you can see there's no \ at all... :?

mhuibers
8 Mar 2007, 6:11 AM
It is confusing. However I did the following:

var personData=[data.value]; --> result empty grid with one empty row

if I read the value and use that exact same string and hardcode it like this:
var personData=[{"Aliases":"aliases1","FirstName":"firstname1","LastName":"lastname1"}];

it works.

I have absolutely no clue what is wrong

Ps. Indeed the data.value output does not contain any '\'

BernardChhun
8 Mar 2007, 6:28 AM
It is confusing. However I did the following:

var personData=[data.value]; --> result empty grid with one empty row

if I read the value and use that exact same string and hardcode it like this:
var personData=[{"Aliases":"aliases1","FirstName":"firstname1","LastName":"lastname1"}];

it works.

I have absolutely no clue what is wrong

Ps. Indeed the data.value output does not contain any '\'

indeed I'm confused as well...hmmm do you have any docs on the implementation of the JSON standard for your JSON library? It's definitely what happens in-between that is a totally weird.

mhuibers
8 Mar 2007, 6:52 AM
I do not have any documentation on the newtonsoft json implementation.

For some reason the data returned seems to be correct. It simply does not show up in the grid.
If something goes wrong the grid will only display its columnheaders and no rows.
In this case it does show one row however it is empty.

http://i17.tinypic.com/2n01yy1.jpg

(don't mind the different names of the columnheaders)

BernardChhun
8 Mar 2007, 7:29 AM
I do not have any documentation on the newtonsoft json implementation.

For some reason the data returned seems to be correct. It simply does not show up in the grid.
If something goes wrong the grid will only display its columnheaders and no rows.
In this case it does show one row however it is empty.

http://i17.tinypic.com/2n01yy1.jpg

(don't mind the different names of the columnheaders)

can you post a screenshot of firebug's console showing the response tab as well? since you are using aspx, you must be on IE so go there to get firebug: http://getfirebug.com/

mhuibers
8 Mar 2007, 7:54 AM
Used FireBug to get the response output:

http://i17.tinypic.com/4hmmz4i.png

(had to remove fieldnames and data ...sorry for that)

As you can see it is not the output style you have. but this is what newtonsoft.json returns ??!!

Animal
8 Mar 2007, 8:14 AM
It is confusing. However I did the following:

var personData=[data.value]; --> result empty grid with one empty row

if I read the value and use that exact same string and hardcode it like this:
var personData=[{"Aliases":"aliases1","FirstName":"firstname1","LastName":"lastname1"}];

it works.

I have absolutely no clue what is wrong

Ps. Indeed the data.value output does not contain any '\'

To send one line of Grid data back from a Java servlet:

out.write("[{\"Aliases\":\"aliases1\",\"FirstName\":\"firstname1\",\"LastName\":\"lastname1\"}]");

And you don't need to touch it at all on the browser.

mhuibers
8 Mar 2007, 8:20 AM
To send one line of Grid data back from a Java servlet:

out.write("[{\"Aliases\":\"aliases1\",\"FirstName\":\"firstname1\",\"LastName\":\"lastname1\"}]");

And you don't need to touch it at all on the browser.

Animal,

What exactly do you mean? for your information i am not using java at all (apart from javascript then).

Animal
8 Mar 2007, 8:25 AM
OK, you're using a MemoryProxy.

Just pass in an Array then. Simple.

mhuibers
8 Mar 2007, 8:28 AM
But what is wrong with my string then?

Is incorrectly formatted according to you?

Animal
8 Mar 2007, 9:08 AM
String?

You need an Array of row objects:



[
{"Aliases":"aliases1","FirstName":"firstname1","LastName":"lastname1"},
{"Aliases":"aliases2","FirstName":"firstname2","LastName":"lastname2"},
]

mhuibers
8 Mar 2007, 11:48 AM
So just for clarification (since i am completely new to this).

what does this returned value represent? is it something valid?

{"Aliases":"aliases1","FirstName":"firstname1","LastName":"lastname1"}

and if it is valid .... why is the grid not displaying it?

I know ...i've been asking this over and over ... but i do not seem to understand what is happening.

BernardChhun
8 Mar 2007, 12:07 PM
So just for clarification (since i am completely new to this).

what does this returned value represent? is it something valid?

{"Aliases":"aliases1","FirstName":"firstname1","LastName":"lastname1"}

and if it is valid .... why is the grid not displaying it?

I know ...i've been asking this over and over ... but i do not seem to understand what is happening.

it represents a single object with 3 properties. The grid takes an array of those to display his rows.

so these [ ] has to wrap every row.

[{"Aliases":"aliases1","FirstName":"firstname1","LastName":"lastname1"}]

mhuibers
8 Mar 2007, 3:01 PM
BernardChhun,

Thanks for your explanation, really appreciate it!

So i take it that the result i get back (as posted earlier) is ok.

Still as you said earlier...it is a bit strange that the grid doesn't show it?

anyway ..the only thing i can do now is troubleshoot again and hopefully one of you guys (or myself) have a brainwave and bring up an explanation :? ...again thanks for your help

Michiel

JeffHowden
8 Mar 2007, 4:10 PM
[...] so these [ ] has to wrap every row.

[{"Aliases":"aliases1","FirstName":"firstname1","LastName":"lastname1"}]

Just to clarify further, the square brackets need to wrap all rows, not each/every.


mydata = [
/* Row 1 */ { id: 1, name: 'Foo' },
/* Row 2 */ { id: 2, name: 'Bar' },
/* Row 3 */ { id: 3, name: 'Baz' },
/* Row 4 */ { id: 4, name: 'Qux' },
/* Row 5 */ { id: 5, name: 'Quux' },
/* Row 6 */ { id: 6, name: 'Corge' },
/* Row 7 */ { id: 7, name: 'Grault' },
/* Row 8 */ { id: 8, name: 'Garply' },
/* Row 9 */ { id: 9, name: 'Waldo' },
/* Row 10 */ { id: 10, name: 'Fred' }
];

Now, the variable "mydata" is an array where each element is an object with the properties "id" and "name". However, to get your grid to work, you need a bit more info: a property that contains the total number of records in your query on the server (the JSON returned should only be a subset of that if you're using paging) and a property to hold the array of objects that represents the resultset.


{ totalCount: 781, data: [
/* Row 1 */ { id: 1, name: 'Foo' },
/* Row 2 */ { id: 2, name: 'Bar' },
/* Row 3 */ { id: 3, name: 'Baz' },
/* Row 4 */ { id: 4, name: 'Qux' },
/* Row 5 */ { id: 5, name: 'Quux' },
/* Row 6 */ { id: 6, name: 'Corge' },
/* Row 7 */ { id: 7, name: 'Grault' },
/* Row 8 */ { id: 8, name: 'Garply' },
/* Row 9 */ { id: 9, name: 'Waldo' },
/* Row 10 */ { id: 10, name: 'Fred' }
]
}

brian.moeskau
8 Mar 2007, 4:21 PM
I'm curious as to why -- if you're already using AjaxPro -- you're not returning typed objects via methods with [AjaxPro.AjaxMethod] attributes? The AjaxPro library will serialize the objects to JSON for you so that you can then use the JS objects on the client without eval'ing them from strings first. Dealing with a typed API on the server is a lot more convenient too.

Granted, this does not directly answer your issue, just curious why. I use AjaxPro calls directly in my stuff and it works great.

mhuibers
9 Mar 2007, 2:31 AM
bmoeskau: Many thanks for your info. It really helped me understand json

Jeff: You are right ... now that i use AjaxPro it is indeed much easier to return objects. So i am doing that at the moment and it seems to work perfectly!

So my next challenges will be ... paging, filtering and displaying little images in the grid based on values within the objects that are returned.

Again thanks very much everyone for your excellent help!

Michiel

mhuibers
9 Mar 2007, 12:44 PM
@bmoeskau: I do have one more question. I return my collection and its been serialized to json, in other words my grid does show all the data. Perfect!

Now, i understand from other posters that paging is only possible if you supply a 'recordcount', often called 'totalCount'. After examining the json i get from AjaxPro I realized that it does not show anything like that.

Ok this is what I do:

CS Code:


[AjaxMethod]
public CORECollection<LEPPerson> GetPersons()
{
CORECollection<LEPPerson> persons=LEPBusiness.GetBusinessLayer().GetPersonsForSite("eufor1");
return persons;
}


JS Code:

var InitPersonGrid =
{
init: function()
{
_Default.GetPersons(getPersons_callback);
}
};
Ext.onReady(InitPersonGrid.init, InitPersonGrid, true);


function getPersons_callback(data)
{
// Create data object containing persons retrieved from LEPBusiness layer (Json result)
var personData=[data.value];

// Create a record container, define column names and datacolumn mapping
var persons = Ext.data.Record.create
([
{name: 'identifier', mapping: 'Identifier'},
{name: 'firstName', mapping: 'FirstName'},
{name: 'lastName', mapping: 'LastName'},
{name: 'aliases', mapping: 'Aliases'},
{name: 'dobu', mapping: 'DateOfBirth', type: 'date', dateFormat: 'timestamp'},
{name: 'currentStatus', mapping: 'CurrentListStatus'},
{name: 'relationsCount', mapping: 'RelationsCount'},
{name: 'imageDetailsCount', mapping: 'ImageDetailsCount'},
{name: 'fileDetailsCount', mapping: 'FileDetailsCount'} ,
{name: 'nationality', mapping: 'Nationality'},
{name: 'ethnicity', mapping: 'Ethnicity'},
{name: 'religion', mapping: 'Religion'},
{name: 'comments', mapping: 'Comments'},
{name: 'sex', mapping: 'Gender'}
]);

// create reader that reads into person records
var reader =new Ext.data.JsonReader
(
{
root:'',
id: 'identifier'
}, persons
);

var ds = new Ext.data.Store
({
// Create proxy and define the reader to use
proxy: new Ext.data.MemoryProxy(personData[0]),
reader: reader,
remoteSort: true
});
ds.setDefaultSort('lastName', 'desc');

//Custom renderers
function renderImages(value,p,record)
{
var status= GetStatusImage(record.data['currentStatus']);
var file=GetFilesImage(record.data['fileDetailsCount']);
var image=GetImagesImage(record.data['imageDetailsCount']);
var relation=GetRelationsImage(record.data['relationsCount']);
return status+file+image+relation;
}

function renderLast(value, p, r){
return String.format('{0}', value.dateFormat('d F Y'));
}

function renderPersonsWithComments(value, p, record){
var result=(record.data['comments']==String.Empty||record.data['comments']=='')?'No comments available':record.data['comments'];
var comm='<div style="float: right;padding:5px 5px 5px 5px">';
comm+='<img src=\'bush_head2.jpg\' width=75px height=75px/>';
comm+='</div><div style="float: right;padding:5px 5px 5px 5px">' + result;
comm+='</div>';
return String.format('{0}
{1}', value, comm);
}

function renderPersonsWithoutComments(value){
return String.format('{0}', value);
}
function renderGender(value){
switch (value){
case (1):
return 'Male';
case (2):
return 'Female';
default:
return 'Unknown';
}
}
// Define columns for grid and link to datafield in dataset (dataIndex)
var cm = new Ext.grid.ColumnModel
([
{
header:'ID',
renderer: renderImages,
dataIndex:'Status'
},
{
id:'lastname',
header:'Last Name',
dataIndex:'lastName',
width: 420,
renderer: renderPersonsWithoutComments,
css: 'white-space:normal;'
},
{
header:'First Name',
dataIndex:'firstName'
},
{
header:'Aliases',
dataIndex:'aliases'
},
{
header:'DOB',
renderer: renderLast,
dataIndex:'dobu',
align: 'right'
},
{
header:'Sex',
dataIndex:'sex',
renderer:renderGender
},
{
header:'Ethnicity',
dataIndex:'ethnicity'
},
{
header:'Nationality',
dataIndex:'nationality'
},
{
header:'Religion',
dataIndex:'religion'
}
]);
cm.defaultSortable = true;

// create the grid and place it in a control with id 'container' (defined on page)
var grid1 = new Ext.grid.Grid('container',
{
ds: ds,
cm: cm,
selModel: new Ext.grid.RowSelectionModel({singleSelect:true}),
enableColLock:false,
autoSizeColumns:false
});


grid1.on('rowclick', function(grid1, rowIndex, e)
{
//todo
});
grid1.render();

var gridFoot = grid1.getView().getFooterPanel(true);

// add a paging toolbar to the grid's footer
var paging = new Ext.PagingToolbar(gridFoot, ds, {pageSize: 25});
paging.add('-', {
pressed: false,
enableToggle:true,
text: 'Detailed View',
cls: 'x-btn-text-icon details',
toggleHandler: toggleDetails
});


// create a floating label with display info
var displayInfo = gridFoot.createChild({cls:'paging-info'});
ds.on('load', function(){
var count = ds.getCount();
var msg = count == 0 ?
"No persons to display" :
String.format(
'Displaying persons {0} - {1} of {2}',
paging.cursor+1, paging.cursor+count, ds.getTotalCount()
);
displayInfo.update(msg);
});
ds.load({params:{start:0, limit:100}});
function toggleDetails(btn, pressed)
{
cm.getColumnById('lastname').renderer = pressed ? renderPersonsWithComments : renderPersonsWithoutComments;
grid1.getView().refresh();
};


}


function GetStatusImage(status)
{
var img='<IMG SRC=\'{0}\' alt=\'{1}\'/>';
switch(status)
{
case 'BLACK':
return String.format(img,"forbidden16.gif","Black listed");
case 'GREY':
return String.format(img,"warning_black16.gif","Grey listed");
case 'GREY ASSOCIATE':
return String.format(img,"warning_red16.gif","Grey by association");
case 'WHITE CLEARED':
return String.format(img,"check_yellow16.gif","White cleared");
default:
return String.format(img,"check16.gif","White listed");
}
return img;
}

function GetFilesImage(count)
{
var img='<IMG SRC=\'{0}\' alt=\'{1}\'/>';
return String.format(img,count>0?'document_attachment.gif':'trans.gif',count>0?count + ' available file(s)':'');
}

function GetImagesImage(count)
{
var img='<IMG SRC=\'{0}\' alt=\'{1}\'/>';
return String.format(img,count>0?'photo_portrait.gif':'trans.gif',count>0?count + ' available image(s)':'');
}

function GetRelationsImage(count)
{
var img='<IMG SRC=\'{0}\' alt=\'{1}\'/>';
return String.format(img,count>0?'users2.gif':'trans.gif',count>0?count + ' relation(s)':'');
}

Result plain text:

"[{\"__type\":\"NC3A.LEP.BusinessLayer.LEPPerson, NC3A.LEP.BusinessLayer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\",\"Aliases\":\"Han\",\"DOBUnknown\":false,\"DriversLicenseNumber\":\"\",\"DriversLicenceExpiryDate\":null,\"Height\":\"1.79\",\"Weight\":\"60\",\"HairColour\":\"BLOND/PLAVA\",\"EyeColour\":\"blue\",\"Comments\":\"The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\r\nThe quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\r\nThe quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\r\nThe quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\r\n\",\"MilitaryPlaceOfService\":\"\",\"MilitaryRank\":\"\",\"MilitaryID\":\"\",\"MilitaryUnit\":\"\",\"MilitaryUnitDuringWar\":false,\"MilitaryPeriodOfService\":\"\",\"ImageDetailsCount\":0,\"FileDetailsCount\":4,\"RelationsCount\":2,\"NationalIDCardType\":\"\",\"NationalIDCardNumber\":\"1297xxxx\",\"CurrentListStatusFriendlyName\":\"White cleared\",\"CurrentListStatus\":\"WHITE CLEARED\",\"PassportNumber\":\"1919191\",\"PassportIssueDate\":null,\"SearchRanking\":null,\"FirstName\":\"Hanneke\",\"MiddleName\":\"\",\"LastName\":\"Sanders\",\"MaidenName\":\"Sanders\",\"DateOfBirth\":new Date(Date.UTC(1976,10,16,23,0,0,0)),\"PlaceOfBirth\":\"Gouda\",\"CountryOfBirth\":\"\",\"IsMale\":false,\"Gender\":2,\"IsDeceased\":false,\"MaritalStatus\":3,\"Ethnicity\":\"\",\"Nationality\":\"Dutch\",\"Religion\":\"Not religious\",\"Connections\":[],\"Identifier\":\"1EUFOR1\",\"IsNew\":false,\"IsValid\":false,\"IsDirty\":false,\"IsDeleted\":false,\"Position\":-1},{\"__type\":\"NC3A.LEP.BusinessLayer.LEPPerson, NC3A.LEP.BusinessLayer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\",\"Aliases\":\"\",\"DOBUnknown\":false,\"DriversLicenseNumber\":\"\",\"DriversLicenceExpiryDate\":null,\"Height\":\"\",\"Weight\":\"\",\"HairColour\":\"\",\"EyeColour\":\"\",\"Comments\":\"The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\r\nThe quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\r\nThe quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\r\nThe quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\r\n\",\"MilitaryPlaceOfService\":\"\",\"MilitaryRank\":\"\",\"MilitaryID\":\"\",\"MilitaryUnit\":\"\",\"MilitaryUnitDuringWar\":false,\"MilitaryPeriodOfService\":\"\",\"ImageDetailsCount\":1,\"FileDetailsCount\":0,\"RelationsCount\":1,\"NationalIDCardType\":\"\",\"NationalIDCardNumber\":\"\",\"CurrentListStatusFriendlyName\":\"White listed\",\"CurrentListStatus\":\"WHITE\",\"PassportNumber\":\"\",\"PassportIssueDate\":null,\"SearchRanking\":null,\"FirstName\":\"Timo\",\"MiddleName\":\"\",\"LastName\":\"Huibers\",\"MaidenName\":\"\",\"DateOfBirth\":new Date(Date.UTC(2004,4,17,22,0,0,0)),\"PlaceOfBirth\":\"\",\"CountryOfBirth\":\"\",\"IsMale\":false,\"Gender\":0,\"IsDeceased\":false,\"MaritalStatus\":0,\"Ethnicity\":\"\",\"Nationality\":\"\",\"Religion\":\"\",\"Connections\":[],\"Identifier\":\"2EUFOR1\",\"IsNew\":false,\"IsValid\":false,\"IsDirty\":false,\"IsDeleted\":false,\"Position\":-1},{\"__type\":\"NC3A.LEP.BusinessLayer.LEPPerson, NC3A.LEP.BusinessLayer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\",\"Aliases\":\"\",\"DOBUnknown\":false,\"DriversLicenseNumber\":\"\",\"DriversLicenceExpiryDate\":null,\"Height\":\"\",\"Weight\":\"\",\"HairColour\":\"\",\"EyeColour\":\"\",\"Comments\":\"The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\r\nThe quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\r\nThe quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\r\nThe quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\r\n\",\"MilitaryPlaceOfService\":\"\",\"MilitaryRank\":\"\",\"MilitaryID\":\"\",\"MilitaryUnit\":\"\",\"MilitaryUnitDuringWar\":false,\"MilitaryPeriodOfService\":\"\",\"ImageDetailsCount\":1,\"FileDetailsCount\":0,\"RelationsCount\":1,\"NationalIDCardType\":\"\",\"NationalIDCardNumber\":\"\",\"CurrentListStatusFriendlyName\":\"White listed\",\"CurrentListStatus\":\"WHITE\",\"PassportNumber\":\"\",\"PassportIssueDate\":null,\"SearchRanking\":null,\"FirstName\":\"Femke\",\"MiddleName\":\"\",\"LastName\":\"Huibers\",\"MaidenName\":\"\",\"DateOfBirth\":new Date(Date.UTC(2006,1,13,23,0,0,0)),\"PlaceOfBirth\":\"\",\"CountryOfBirth\":\"\",\"IsMale\":false,\"Gender\":0,\"IsDeceased\":false,\"MaritalStatus\":0,\"Ethnicity\":\"\",\"Nationality\":\"\",\"Religion\":\"\",\"Connections\":[],\"Identifier\":\"3EUFOR1\",\"IsNew\":false,\"IsValid\":false,\"IsDirty\":false,\"IsDeleted\":false,\"Position\":-1}];/*"

Result show in vs.net 2005 IDE watch
http://i15.tinypic.com/29fsayp.png

Result in browser (without the ablitity to sort or page)
http://i18.tinypic.com/333k7br.png

and

http://i16.tinypic.com/4dpe2r4.png


So the question ultimately is this; how can I make sorting and paging work? Do you guys see anything that is incorrect? I am really sorry to ask these 'silly' questions but I am learning

Thanks once again,

Michiel

brian.moeskau
9 Mar 2007, 2:28 PM
I haven't personally had to implement paging in my stuff, but I think you'd want to wrap your collection object in a container that can also hold the other properties that you need. So from your web method, you'd return something like:


PersonData
|-- RecordCount
|-- PersonCollection
|-- Person1
|-- Person2 ...

Then you would use PersonCollection as your root element for binding to the grid. While I'm not specifically doing paging myself, I am using this same pattern of wrapper objects to pass stuff back to the client and it works fine for me.

mhuibers
9 Mar 2007, 2:32 PM
Can you eloborate a bit more on that ? .... my business layer object is just returning a collection object with objects... these objects are (apparently) correctly serialized. my collection object has properties like 'count' .... so maybe i do not understand you correctly.

brian.moeskau
9 Mar 2007, 3:55 PM
I think the issue is that collections get serialized to arrays of JSON data -- so even though it looks like you're returning a nice rich CORECollection object, in reality, you're really just getting back a simple array of LEPPerson objects in JSON format with none of the extended properties you're probably expecting to be there. This may be a configuration issue -- I'm honestly not sure since I haven't really gone too deeply into the details of customizing what AjaxPro can or cannot return.

In my case, I took the simple approach -- since it's already giving you back the correct LEPPerson array, and all you need in addition to that is the count, you can simply wrap the count and the collection of LEPPersons in an arbitrary containing object so that you can still serialize the entire thing as a single JSON blob with the structure I showed above. Then it's just a matter of mapping the count property to the grid and adding the collection property of the JSON object as your grid root and it should work. :)

mhuibers
10 Mar 2007, 10:57 AM
Ok now that i am able to display my data i would also like to implement sorting and paging. I did read (i think) everything on paging and sorting in this forum but for some reason i can't get it to work.

What I'd like to do is get a very small dataset from the server and at every paging request get a new small set of data for that new page. I tried to implement paging for the entire dataset (800 records) but it doesn't work. The grid shows the entire dataset instead of the ..let's say.. 20 records that I want to display.

Following code snippets tell you what I did in code:


var reader =new Ext.data.JsonReader
(
{
root:'Data',
totalProperty: 'totalCount',
id: 'identifier'
}, persons
);


var paging = new Ext.PagingToolbar(gridFoot, ds, {pageSize: 1});
paging.add('-', {
pressed: false,
enableToggle:true,
text: 'Detailed View',
cls: 'x-btn-text-icon details',
toggleHandler: toggleDetails
});



ds.load({params:{start:0, limit:1}});

my json looks like this:

{"__type":"_Default+MyData, App_Web_qjmiky6w, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null","totalCount":3,"Data":[{"__type":"NC3A.LEP.BusinessLayer.LEPPerson, NC3A.LEP.BusinessLayer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","Aliases":"Han","DOBUnknown":false,"DriversLicenseNumber":"" ETC ETC

So my question really is:
What am I doing wrong regarding sorting and paging. I expected (by setting the limit values) the grid to show only the number of records set in the limit property.

Thanks guys

Michiel

BernardChhun
10 Mar 2007, 11:33 AM
The limit values that has been set has to be treated on the server side.

look closely at firebug's console here:

Here's the paging grid:
http://i15.tinypic.com/49l34he.png

and here are the values that has been posted for the first page:
http://i16.tinypic.com/2u77og1.png

and here's the second page request:

http://i15.tinypic.com/2vimr7a.png

So as you can see you will have to insert these 4 parameters into your SELECT query.


SELECT foo FROM foo WHERE foo ORDER BY sortParameter dirParameter LIMIT startParameter, limitParameter

using the values above you get:


SELECT foo FROM foo WHERE foo ORDER BY ID ASC LIMIT 10, 10

Your server-side will have to send chunks of data to the grid. and don't forget to send the totalCount property to the grid so that the paging works.


SELECT count(foo) FROM foo WHERE foo

As for sorting the above SELECT query will do it automatically. :)

mhuibers
10 Mar 2007, 11:44 AM
Thanks bernard,

However this is what's going on on my side:

I have a business layer that communicates with the data layer. So from the presentation layer (which where the yui-ext stuff comes in) i deal with (as you know from previous posts) business objects and not with the database at all.

I communicate through AjaxPro with my business objects. So i do not have these 4 values.
If I look at firebug typically there are no values ({}).

Do you have any recommendation regarding this setup? I am kind of stuck and as you probably know sorting and paging are kind of important :D

Thanks

Michiel

BernardChhun
10 Mar 2007, 12:25 PM
I have a business layer that communicates with the data layer. So from the presentation layer (which where the yui-ext stuff comes in) i deal with (as you know from previous posts) business objects and not with the database at all.

I communicate through AjaxPro with my business objects. So i do not have these 4 values.
If I look at firebug typically there are no values ({}).

Do you have any recommendation regarding this setup? I am kind of stuck and as you probably know sorting and paging are kind of important :D

Thanks

Michiel

hmm you receive no values at all from the grid? How does your business object knows about the grid's request then? If I understand well, AjaxPro comes in-between the presentation layer and the business layer right? AjaxPro should then receive some kinda communication information so that it sends the correct request to your business layer and so on.

No matter what server-side technology you are dealing with I strongly believe POST & GET values should be catched by the server-side. The first layer to catch the info should be able to transfer that knowledge to the others layers.

If I'm not right about these points, well I'm sorry if I don't understand your situation well Michiel :?

brian.moeskau
10 Mar 2007, 12:47 PM
Bernard is right in that ultimately you will have to be able to pass sort and paging parameters (and probably filter criteria too) all the way to the DAL so that the query that runs can return the appropriate page of data. Either that, or something in your business layer will have to provide the appropriate filter/paging logic prior to returning the results to the client, but either way, you have to pass the parameters to the server in order to get server-side paging/sorting (you can always get everything back and page/sort on the client, is that what you're wanting? I'm assuming not).

For this to work, your server method MUST be able to accept these additional params so that the server can figure out what page of data to return. Instead of:


_Default.GetPersons(getPersons_callback);
... you probably need something like:


_Default.GetPersons('ASC', 10, 'ID', 0, getPersons_callback);
Of course, you'd really be passing variables that you're setting in code based on the current grid state and what's being requested.

Another option is to create a serializable helper object on the server side like 'PagingOptions' with those four properties, and then add one parameter to your server method of that type. The nice thing about that is that you keep the parameter list smaller and more flexible in case you want to add something later. On the client side, you could then pass the appropriate JSON object that will come across to the server as a nice strongly-typed PagingOptions object:


var options = { sortDir: 'ASC', pageSize: 10, sortCol: 'ID', pageNum: 1 };
_Default.GetPersons(options, getPersons_callback);
This assumes that the server is expecting an object with those properties. E.g.:


[Serializable]
public class PagingOptions
{
public string sortDir;
public int pageSize;
public string sortCol;
public int pageNum;
}

mhuibers
12 Mar 2007, 2:56 AM
Brian, Bernard,

First of all i'm sorry i haven't been able to reply any sooner,
Next I fully agree with you guys.

The problem now is that i do not seem to understand the paging mechanism of the pagingtoolbar.
As described above my grid initializes on:


var InitPersonGrid =
{
init: function()
{
_Default.GetPersons('ASC',0,'FirstName',1,getPersons_callback);
}
};

then the grid is really initialized within getPerons_callback.

In there I set the reader:


var reader =new Ext.data.JsonReader
(
{
root:'Data',
totalProperty: 'totalCount',
id: 'identifier'
}, persons
);


Next I set things as the memoryproxy:


var ds = new Ext.data.Store
(
{
proxy: new Ext.data.MemoryProxy(personData[0]),
reader: reader,
remoteSort: true
}
);


Now I create the pagingtoolbar:


var paging = new Ext.PagingToolbar(gridFoot, ds, {pageSize: 1});


Finally I load the data.


ds.load({params:{start:0, limit:1}});


The result I get back is (in my example) 1 object while I really have 3. The reason is that I filter my collection (contains a filterItems arraylist internally). So the returned totalcount=3 while the returned array contains 1 object. Since I implemented it like this my grid shows one object and the pagingtoolbar allows me to click next (until 3). However the data is not changing.


Questions really are:
1. What should initially be loaded by the grid ( a assume a subset of the data dictated by the limit and stat params)?
2. How is the paging handled? Is that done by the paging toolbar or should I implement handlers to get the next subset of data?

Thanks again

Michiel

Animal
12 Mar 2007, 3:52 AM
The paging is handled by the resource at the URL you give to the Ext.data.Store.

It's based upon the start and limit parameters. It is required to return "limit" rows, starting at row "start" of the dataset.

So you are asking for 1 row per page!

But I see you are using a MemoryProxy, so you have all the data in yout browser anyway, you are not using remote paging!

mhuibers
12 Mar 2007, 7:34 AM
Animal,

Thank you for this clarrification. I've got it all to work now.

I created an ashx file where I use the parameters dir,limit,start and sort on my collection class.
Further more I use (obviously) the HttpProxy instead of the MemoryProxy.

Thanks again to all for you patience and help

Cheers

Michiel

starique
12 Mar 2009, 11:59 AM
I am trying out the ext grid.

Jsp page code -
<%
//converting to jason data
String jsondata=
new JSONSerializer().exclude(exclude).serialize(empList);
//here the data prints fine
[{"id":"aaa","wt":20},{"id":"bbb","wt":10},{"id":"ccc","wt":30},{"id":"ddd","wt":50},{"id":"eee","wt":10}]
%>
//storing into hidden field to get in js file
<INPUT TYPE="hidden" id="LOS" NAME="LOS" value="<%=jsondata%>">

//In the java script

var

data = Ext.get('LOS').dom.value;

alert(data); //only prints [{

Ext.grid.dummyData = data;
And the data is null. But in the jsp page I see the data is not null.


any help would be really helpful.