PDA

View Full Version : How to debug loading a Form



chubbard
2 Jun 2007, 3:23 PM
Hi,

I'm just starting out on extjs and I'm loading the form from a json response using the load method. However, I can't seem to figure why the thing isn't loading the results into the form. The json request is completing, but nothing shows up in my Form. How can I debug what extjs is doing so I can figure out what's wrong?

Thanks
Charlie

jsakalos
2 Jun 2007, 3:55 PM
Use Firefox with Firebug for developing and turn on Show XMLHttpRequests in Firebug. Then you can set breakpoints in javascript and you'll see also content of request and response from server.

chubbard
2 Jun 2007, 8:48 PM
I ment anything other than those things. Is there any logging or something that might indicate why it doesn't like it. Can already see, from firebug, that my XHR request is being submitted and that I'm returning a json object that looks correct. So I can confirm that through firefox, but after that nothing happens. Tracing into the code with a debugger is a little tough to find the right spot with all the asyncronous behavior happening. I was hoping for something little less nuts and bolts.

It's also strange that the demo of XML data and Forms is doing the exact same behavior as my application. In the XML demo if you press load button it shows the loading message but the loading message dissappears and nothing happens. The form is not filled in. This is the exact same thing my Forms is doing but I'm using JSON. I can also see the XML being returned in the XHR in firefox without problems, but nothing happens. Just like I can see the JSON being returned from my application without error.

Animal
2 Jun 2007, 11:52 PM
It's not really that difficult. You can debug async server IO by setting breaks in the callbacks.

Use ext-all-debug.js

Step into the load() call (It takes a while for Firebug to find the line in the big file, so be patient), then when in there, type "type : 'load'," (without surrounding double quotes) into the search box that Firebug has.

Then scroll down a little and set a breakpoint in the success method.

Then scroll up a little (Or search for "type : 'default'", and scoll down) and set a break in the failure method.

Then click Continue, and you'll be able to debug the response.

chubbard
3 Jun 2007, 5:30 AM
Yea I figured that all out after wandering around in the code and manually tracing through all of it, but I think found the problem in Ext.data.JsonReader. It looks like JsonReader always expects the JSON data to always be an array. It's not until the end of this function that it creates the Record objects inside a loop governed by the temporary variable c. I know this class is used both with Forms and Grid, but it's really unintuitive, and not explained in the documentation that this is expected. What does it mean in the Form use case for it to be an array? I imagined the form would be a representation of a single object. Actually I'm trying to use the form as an editor for a single row out of my Grid.

It would take much to refactor this code to gracefully handle either case without changing the outside interface. Something like:



if( root.length ) {
for( var i = 0; ... ) {
readARecord( root[i] );
}
} else {
readARecord( root );
}


Here is the code I'm refering to:



readRecords: function (o) {
this.jsonData = o;
var s = this.meta, Record = this.recordType, f = Record.prototype.fields, fi = f.items, fl = f.length;
if (!this.ef) {
if (s.totalProperty) {
this.getTotal = this.getJsonAccessor(s.totalProperty);
}
if (s.successProperty) {
this.getSuccess = this.getJsonAccessor(s.successProperty);
}
this.getRoot = s.root ? this.getJsonAccessor(s.root) : (function (p) {return p;});
if (s.id) {
var g = this.getJsonAccessor(s.id);
this.getId = (function (rec) {var r = g(rec);return (r === undefined || r === "") ? null : r;});
} else {
this.getId = (function () {return null;});
}
this.ef = [];
for (var i = 0; i < fl; i++) {
f = fi[i];
var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
this.ef[i] = this.getJsonAccessor(map);
}
}
// RIGHT HERE IS WHERE IT EXPECTS THIS TO BE AN ARRAY!
var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
if (s.totalProperty) {
var v = parseInt(this.getTotal(o), 10);
if (!isNaN(v)) {
totalRecords = v;
}
}
if (s.successProperty) {
var v = this.getSuccess(o);
if (v === false || v === "false") {
success = false;
}
}
var records = [];
for (var i = 0; i < c; i++) {
var n = root[i];
var values = {};
var id = this.getId(n);
for (var j = 0; j < fl; j++) {
f = fi[j];
var v = this.ef[j](n);
values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue);
}
var record = new Record(values, id);
record.json = n;
records[i] = record;
}
return {success:success, records:records, totalRecords:totalRecords};
}

Animal
3 Jun 2007, 5:37 AM
Or you could provide your own Reader. Just specify a reader:myReader in the config of your form.

The reader must implement the read(XHRresponse) method which returns an object containing an Array calls "records", and a boolean called "success". Element zero of the "records" Array is the single Record object representing the returned data.