PDA

View Full Version : Newbie - Having trouble getting ExtJS v4 to read JSON Array



samuurai
30 Dec 2011, 5:02 PM
Hi,

I have a very basic application here:


/**
* @example Simple Grid
*
* A basic grid that renders itself to the document body.
*/
Ext.require('Ext.data.Store');
Ext.require('Ext.grid.Panel');

Ext.define('Email', {
extend: 'Ext.data.Model',
fields: [ 'data' ],
proxy: {
type: 'ajax',
url: '/index.php/ezmail',
reader: {
type: 'json',
root: 'data'
}
}
});

Ext.onReady(function() {

var emailStore = Ext.create('Ext.data.Store', {
autoLoad:true,
model: 'Email',
});

Ext.create('Ext.grid.Panel', {
renderTo: Ext.getBody(),
store: emailStore,
width: 400,
height: 200,
title: 'Application Users',
columns: [
{
text: 'Email',
width: '100%',
sortable: true,
hideable: false,
dataIndex: 'emailDir'
}
]
});

});

And the url returns this JSON data:


{"success":true,"data":["AQUA_MAIL40_02","AQUA_MAIL32","AQUA_MAIL39_01","AQUA_MAIL29_01","AQUA_MAIL24_01"]}

The window loads and I can see the XHR request, which is valid, but nothing appears in the grid. I also get no JS errors.

Models are new to me, am I doing something wrong?

Thank you!

skirtle
31 Dec 2011, 6:20 AM
I'm afraid you've run into an edge case. There's an active feature request to support this: EXTJSIV-4569.

Models are designed to have multiple fields and the standard readers reflect that. The flat array format that you're using doesn't make sense with multiple fields, so it isn't supported. However, I entirely agree that it makes sense for a single field, hence the feature request.

The easiest way to get this to work is just to change your response format.

If you really want to stick with the current format then you'll have to do a bit of trickery. I haven't tested it but the code would be something like this:


Ext.define('Email', {
extend: 'Ext.data.Model',
fields: [ 'emailDir' ],
proxy: {
type: 'ajax',
url: '/index.php/ezmail',
reader: {
type: 'json',
root: 'data',
getResponseData: function(response) {
var data = Ext.data.reader.Json.prototype.getResponseData.call(this, response);

if (data && Ext.isArray(data.data)) {
data.data = Ext.Array.map(data.data, function(val) {
return {emailDir: val};
});
}

return data;
}
}
}
});

The method getResponseData is responsible for extracting the decoded JSON from the XHR response. Here I've replace it with an implementation that maps your original array format to one that can be read by the reader.

samuurai
31 Dec 2011, 9:21 AM
Hi Skirtle, Thanks for your detailed response. I couldn't get that to work, still shows a blank grid.

How should the JSON data be structured to be valid for the Model? I'll try changing it on the server side.

Thanks

skirtle
31 Dec 2011, 9:49 AM
The format I was aiming to create with my client-side trickery was this:


{
"success": true,
"data": [
{"emailDir": "AQUA_MAIL40_02"},
{"emailDir": "AQUA_MAIL32"},
...
]
}

That's the same format I'd advise using if you want to change your server.

Changing the code on the server is probably the cleaner of the techniques but I would strongly advise you to persevere with the client-side technique until you get it working. As a newbie there is a lot of good experience to be gained from getting both techniques to work. Giving up on a perfectly good way to do something just because you can't get it to work is a bad habit to pick up, you need to learn the tricks for debugging instead.

Try adding some logging or a breakpoint into my getResponseData method. The debugging tools that come with browsers these days are excellent. It should be possible to quickly ascertain whether or not that method is being called and whether it is returning the right thing. If it is then it implies that your problem lies elsewhere.

If you can post your full code (like you did originally) with the modifications I suggested I'd be happy to help figure out what the problem is.

samuurai
1 Jan 2012, 5:01 AM
Finally figured it out.. I spent hours on this and found that it had been downloading the JSON ever since I used your code. I learned how to troubleshoot the whole process and added listeners on load: etc.

In the end, I found that having the column [{ width: '100%' }] on the Grid was placing it out of view for some reason.

Still, a great learning experience.. Thanks a lot!

skirtle
1 Jan 2012, 7:17 AM
Ah yes, I probably should have spotted that. Percentages are not valid as widths or heights in most circumstances, including columns. The width has to be a number of pixels or you can use flex to specify a proportion. So for a single column to be 100% width you'd just give it a flex value, say flex: 1.

samuurai
1 Jan 2012, 9:23 AM
Thanks for this. Silly little percentage sign caused me to learn a lot of other stuff I would've had to learn next anyway... my app is coming along !!