PDA

View Full Version : [UNKNOWN][3.0.0] HttpProxy bug/breaking change/documentation error



AdamDawes
22 Jul 2009, 3:01 AM
I've struggled for several hours today to fix up a problem with AJAX callbacks since moving from Ext 2.2 to Ext 3.0. Everything else in Ext 3.0 seems to be working fine, but this one took considerable effort to track down. I think I finally have the answer now so I thought I'd share it so that (a) anyone else with the problem might find it useful, and (b) if this is actually a bug it can be fixed for a future release.

This appears to be a breaking change from Ext JS 2.2, and I think it either a bug in Ext or a documentation error or both.

I'm using an AJAX callback to populate values within a ComboBox control. I have set my combobox up as follows:



var extOriginPort_recorddef = Ext.data.Record.create([{name: 'code'}, {name: 'desc'}]);
var extOriginPort_reader = new Ext.data.JsonReader({totalProperty: 'results',root: 'rows'}, extOriginPort_recorddef);
var extOriginPort = new Ext.form.ComboBox({
"id" : 'extId_OriginPort',
"transform" : 'OriginPort',
"triggerAction" : 'all',
"forceSelection" : true,
"typeAhead" : true,
"typeAheadDelay" : 0,
"resizable" : true,
"store" : new Ext.data.Store({
"proxy" : new Ext.data.HttpProxy({url: '', method: 'GET'}),
"reader" : extOriginPort_reader,
}),
"mode" : 'remote',
"displayField" : 'desc',
"valueField" : 'code'
});


After creation, each time my code wishes to update the list items, it was setting the proxy url to the required value and calling the store's reload method:



extOriginPort.store.proxy.conn.url = new_query_url;
extOriginPort.store.reload();


This worked fine in Ext 2.2, but in version 3.0 I get the following exception:


Ext.data.DataProxy: DataProxy attempted to execute an API-action but found an undefined url / function. Please review your Proxy url/api-configuration. arg=read

I've traced this through into Ext and the exception is being thrown as follows:

- When I call into store.reload, Ext calls into store.load.
- This then calls into store.execute, passing in 'read' as the first parameter (the action). This action is hard-coded and I don't appear to be able to override it.
- store.execute fires the beforeload event without any problem, and then calls into its proxy.request method, passing in the read action from the Ext.data.Api.actions array.
- proxy.request finds that the api.read action is undefined and so is the proxy.load property, and so it throws the exception.

If I set the url into the store.proxy.api.load property (as described in the documentation for the api config item of the HttpProxy object) the same thing occurs, as the code in proxy.request doesn't check api.load. It does however check this.load. I tried setting store.proxy.load to be my request Url and this then passes the check at the beginning of proxy.request and doesn't throw an exception at that point. It then carries on as follows:

- Calls into doRequest passing in an action of "read" once again
- Partway through sees that this.conn.url is null and calls into buildUrl to construct it
- buildUrl selects either this.api["read"] value (which is undefined) or this.url (which is also undefined) and so it now throws an invalid-url exception.

I managed to get this to work in the end by setting the proxy url as follows:



extOriginPort.store.proxy.setApi('read', new_query_url);


Note that this is using the read api action, which the code in Ext has been checking throughout, and not the load or api.load properties mentioned in the documentation, which I couldn't get to work at all.

To sum all of this up, I think that the following inconsistencies exist in the code and documentation:

- proxy.request needs to additionally check to see whether the url property has been set, and if so allow the request to continue instead of throwing an exception. I think this change will restore backward compatibility with Ext JS 2.2.

- The documentation for HttpProxy states that the URL can be set either into the store.proxy.api.load property or using the store.proxy.SetApi('load', 'changed2.php') function. However the code in proxy.request checks the proxy.load property, not the proxy.api.load property. Presumably the documentation is incorrect here, but either way, the code and docs don't seem to match on this point.

- buildUrl doesn't take the proxy.load property into account and instead observes only the read api and proxy.url. But we can't actually get here with just proxy.url set due to the exception being thrown in proxy.request. I think this should additionally check proxy.load (or maybe proxy.api.load?) in order to be consistent with the rest of the code.

Unless I'm misunderstanding what is going on inside Ext (I'm not an expert on its inner workings) this would appear to restore compabitility with Ext JS 2.2 and also be more consistent in operation.

I'd be very interested in any thoughts on all of this from those more experienced with how Ext works than I am.

Thanks and regards,