PDA

View Full Version : Intercepting Json stuff.



TotoTitus
3 Sep 2010, 6:47 AM
On the brink of giving up.


function GET_MESSAGES()
{
//TODO: HANDLE INCOMING MESSAGES
Ext.Ajax.request({
url: 'get_messages.php',
method: 'POST',
success: function(response) {
var success = Ext.decode(response.responseText).success;
if(success) {
var root = Ext.decode(response.responseText).root;
var reader = new Ext.data.JsonReader({
fields: ['message', 'sender']
});
var records = reader.readRecords(root);
//What do i do next ? The documentation ain't helpin'.
}
else {
Ext.Msg.alert('FAIL', 'How come you\'re receiving messages without being logged?');
document.location = 'index.html';
}
},
failure: function() {
Ext.Msg.alert('Whoopsie.', 'Something\'s going bad on the server side.');
}
});
}


This function retrieves json data from the server: a success flag, and a root containing nodes with the following fields: message and sender.
All i want to do is so loop through the nodes of the root and process them manually.
Something like this:

for(rec in records_variable)
{
var sender = rec.sender;
var msg = rec.message;
other stuff
}
ok, maybe a bit different, but you get the idea.
thanks. (a lot ! _)

3 Sep 2010, 9:06 AM
Why are you using Ext.Ajax to remotely load a data store? Why not use the JsonStore class's load method? The documentation is well written there.

Condor
3 Sep 2010, 9:11 AM
for (var i = 0; i < records.records.length; i++) {
var rec = records.records[i];
...
}

TotoTitus
3 Sep 2010, 11:10 AM
Why are you using Ext.Ajax to remotely load a data store? Why not use the JsonStore class's load method? The documentation is well written there.

I did not want to use a full blown store for this task - i reckoned i would use stores to load stuff only into other things which require stores (like listviews).
So even if i used a store, had i not needed to still manually process the data ?

3 Sep 2010, 11:12 AM
the processing of the data could be automated by means of a fields "convert" method. I have not seen people use a reader outside of the json store, which is why i ask. You don't need a 'reader' to process generic javascript objects.

TotoTitus
3 Sep 2010, 11:33 AM
Condor, your response is good, but my initial code is bad.


var root = Ext.decode(response.responseText).root;
var records_collection = reader.readRecords(root);

This code of mine throws this error:
o is null
chrome://firebug/content/blank.gif if(o.metaData){
ext-all-debug.js (line 23410)

As jgarcia pointed out, my example is not best practice, and i did not know that. I should use a JsonStore to load up my stuff, and a Task to periodically do this. I have used a JsonStore to fill a ListView, which knew inherently how use the store data.
How would i manually access the root and well, do the for(blabla) thing i was trying to do ?

I see that JsonStore has a fields property, but beyond that, i'm blank.

TotoTitus
4 Sep 2010, 12:32 AM
bump

Condor
4 Sep 2010, 1:12 AM
That error clearly indicates that Ext.decode(response.responseText).root returns undefined.

Does your data actually have a 'root' property?

steffenk
4 Sep 2010, 2:31 AM
as Jay already mentioned, use a store which makes it easy. Use load listener to enumerate manually through the records.

TotoTitus
4 Sep 2010, 4:42 AM
Taking all your answers into account (i hope), i switched to a store.



var MESSAGES_STORE = new Ext.data.JsonStore({
url: 'get_messages.php',
root: 'root',
messageProperty: 'message',
fields: ['sender', 'message']
});
The Json response looks like this : '{success: true, message: "errormsg_or_something_else", root:'.json_encode($msg_array_from_database.'}';
The only difference from last time is that i added a 'message' property to process errors, should they appear.

And my new loading function:


function GET_MESSAGES_2()
{
MESSAGES_STORE.load({
callback: function(records, options, success) {
if(success) {
Ext.Msg.alert('yes!!');
//TODO: HANDLE INCOMING MESSAGES
// for(i in records) do whatever_i_wish
}
else { //alert(success);
/*var msg = this.getMessage;
if(msg == "log") {
Ext.Msg.alert('FAIL', 'How come you\'re receiving messages without being logged?');
}
else if(msg == "server") {
Ext.Msg.alert('Whoopsie. Couldn\'t get new messages', 'Something\'s going bad on the server side.');
}
else if(msg == "ok") {
Ext.Msg.alert('Whoopsie. Couldn\'t get new messages', 'This never should have happened. Please report this error.');
}
else {
Ext.Msg.alert('Whoopsie. Couldn\'t get new messages', 'This NEVER should have happened. Please report this error.');
}*/
}
}
});
}
Much of the code is commented out.

For some reason, the 'success' flag is amost always 'false'.
And i have to mention, that most of the time, the 'root' property is null, because there are no new messages.
What am i doing wrong?

My JSON always reports success:true, yet the code branches on success:false. (checked with FirebUg)

TotoTitus
4 Sep 2010, 6:10 AM
Never mind, root:null always causes the success flag to go false. I'm intercepting that as a separate case.

Edit : Update.
Somehow, i'm not interpreting the JSON properly.



function GET_MESSAGES()
{
MESSAGES_STORE.load({
callback: function(records, options, success) {
if(success) {
var bleh = '';
for(var rec in records) {
bleh+=rec.name; //debug stuff
}
if(bleh!='')
Ext.Msg.alert(bleh,bleh);
}
else {
var msg = this.getMessage; //Here! this does not work.
if(msg == "log") {
Ext.Msg.alert('FAIL', 'How come you\'re receiving messages without being logged?');
}
else if(msg == "server") {
Ext.Msg.alert('Whoopsie. Couldn\'t get new messages', 'Something\'s going wrong, or not going on at all on the server side.');
}
else if(msg == "ok") {
DO_NOTHING(); /**This branch means no new messages have arrived. Well, at least it should. **/
}
else {
//Ext.Msg.alert('Whoopsie. Couldn\'t get new messages', 'This NEVER should have happened. Please report this error.');
Ext.Msg.alert(msg,msg);
}
}
}
});
}

var msg = this.getMessage, where this refers to the current store. For some reason, msg is always null, though, just as an example, my Json is valid:

die('{success: false, message: "log"}');
That's a bit of PHP which generates my Json in case the user is not logged, and somehow he made a request to fill up the jsonstore.
And my store is configured correctly:


var MESSAGES_STORE = new Ext.data.JsonStore({
url: 'get_messages.php',
root: 'root',
messageProperty: 'message',
fields: ['sender', 'message']
});

So, why am i failing to intercept the 'message' part of my json ?

TotoTitus
5 Sep 2010, 5:25 AM
Update 2:

Threw away both JsonStore and JsonReader.

This is my new code:



function GET_MESSAGES()
{
Ext.Ajax.request({
url: 'get_messages.php',
method: 'POST',
success: function(response) {
var json = Ext.decode(response.responseText);
var success = json.success;
var root = json.root;
var msg = json.message;
if(success) {
if(root != "[]") {
/**
The empty root indicator should be an empty array [], but for some reason, if the server
returns [] simply, javascript does not interpret it as being the empty array, so instead
i'm using a "[]" string indicator. Sad? Yes. Effective? Don't know.
**/
for(var i=0; i<root.length; i++) {
var record = root[i];
OPEN_WINDOW(record.sender);
RECEIVE_MESSAGE(record.sender, record.message);
}
}
}
else {
if(msg == "log") {
Ext.Msg.alert('FAIL', 'How come you\'re receiving messages without being logged?');
document.location = 'index.html';
}
else if(msg == "server") {
Ext.Msg.alert('Whoopsie. Couldn\'t get new messages', 'Something\'s going wrong, or not going on at all on the server side.');
}
else if(msg == "ok") {
Ext.Msg.alert('Whoopsie. Couldn\'t get new messages', 'This never should have happened. Please report this error.');
}
else {
Ext.Msg.alert('Whoopsie. Couldn\'t get new messages', 'This NEVER should have happened. Please report this error.');
}
}
},
failure: function() {
Ext.Msg.alert('Whoopsie. Couldn\'t get new messages', 'Something\'s going bad on the server side.');
}
});
}


I am using only Ext.Decode(), and it made life a bit easier.
Only one problem remains (of those which i can see) :



if($msg_array)
echo '{success: true, message: "ok", root:'.json_encode($msg_array).'}';
else
echo '{success: true, message: "ok", root: "[]"}';


This is my PHP code for returning Json, where $msg_array is drawn from the database.
I wanted to simply return root:[], as an empty array, to Javascript, in the case $msg_array were null, but for some reason, [] does not equate to the empty array (???), so i am forced to return a string literal as flag.

TotoTitus
5 Sep 2010, 10:50 PM
Never mind, i left out both jsonreader and jsonstore.
Here's my function:



function GET_MESSAGES()
{
Ext.Ajax.request({
url: 'get_messages.php',
method: 'POST',
success: function(response) {
var json = Ext.decode(response.responseText);
var success = json.success;
var root = json.root;
var msg = json.message;
if(success) {
if(root != "[]") {
/**
The empty root indicator should be an empty array [], but for some reason, if the server
returns [] simply, javascript does not interpret it as being the empty array, so instead
i'm using a "[]" string indicator. Sad? Yes. Effective? It works...sort of.
**/
for(var i=0; i<root.length; i++) {
var record = root[i];
OPEN_WINDOW(record.sender);
RECEIVE_MESSAGE(record.sender, record.message);
}
}
}
else {
if(msg == "log") {
Ext.Msg.alert('FAIL', 'How come you\'re receiving messages without being logged?');
document.location = 'index.html';
}
else if(msg == "server") {
Ext.Msg.alert('Whoopsie. Couldn\'t get new messages', 'Something\'s going wrong, or not going on at all on the server side.');
}
else if(msg == "ok") {
Ext.Msg.alert('Whoopsie. Couldn\'t get new messages', 'This never should have happened. Please report this error.');
}
else {
Ext.Msg.alert('Whoopsie. Couldn\'t get new messages', 'This NEVER should have happened. Please report this error.');
}
}
},
failure: function() {
Ext.Msg.alert('Whoopsie. Couldn\'t get new messages', 'Something\'s going bad on the server side.');
}
});
}

The only problem is i have to use the "[]" string literal in order to flag that the root of the result is empty. I wanted to do something like root:[], but ExtJS doesn't interpret that as being the empty array. (if server response is {success: true, message:"ok", root:[]} then doing root == [] will return false. Odd). So instead i use a string literal "[]". Could've been any string though, i chose this one.

Condor
6 Sep 2010, 1:32 AM
if (Ext.isEmpty(root)) {
...
}

TotoTitus
6 Sep 2010, 2:15 AM
Thinking back, it makes sense that the [] returned from the server does not equate to an empty array, because "empty array", is not a constant, and two empty arrays need not have the same reference.

thanks !

TotoTitus
6 Sep 2010, 4:19 AM
Even though i avoided trying to catch the jsondata with a JsonStore, there's another part in my code, where i can't avoid it. Only this time the root of the response gets processed by a listview, so i don't have to worry about that. What i do need, though, i getting the 'message' property.



function UPDATE_BUDDIES_STATUS()
{
BUDDIES_STORE.load({
callback: function(records, options, success) {
var msg = this.jsonData.message;
var root = this.jsonData.root;
if(success) {
Ext.Msg.alert(msg,msg);
var listv = BUDDY_LIST.getComponent('listv');
var lastselection = listv.getNode(listv.store.getById(CURRENT_SELECTION));
listv.select(lastselection);
}
else {
var msg = this.jsonData.message;
if(msg == "log") {
Ext.Msg.alert('FAIL', 'How come you\'re receiving buddies update without being logged?');
document.location = 'index.html';
}
else if(msg == "server") {
Ext.Msg.alert('Whoopsie. Couldn\'t get buddies update', 'Something\'s going wrong, or not going on at all on the server side.');
}
else if(msg == "ok") {
DO_NOTHING(); /** Means there are no buddies in the list. Well, at least it should. **/
}
else {
Ext.Msg.alert('Whoopsie. Couldn\'t get buddies update', 'This NEVER should have happened. Please report this error.');
}
}
}
});
}


The actual loading of the store works, but i can't get the 'message' property of the jsonresponse.
I tried using the jsonresponse property, thinking that it might work, given the inclusion of a jsonreader into the jsonstore. But i failed. I also assumed (correctly i guess) that "this" is in the scope of the store.

Condor
6 Sep 2010, 4:48 AM
The callback is indeed scoped to the store (so 'this' is the store) and jsonData is a property of the reader, so you need:

var msg = this.reader.jsonData;

TotoTitus
6 Sep 2010, 7:59 AM
Thanks Condor ! You are a great dude !

I did not see "reader" listed in the properties tab of the JsonStore (in the API doc) so it got me confused.
now it works.