PDA

View Full Version : Named Arguments



Gjslick
22 Dec 2009, 8:12 PM
Hey, does anyone know if/when Ext will be implementing named arguments for Ext.Direct calls?

AndreaCammarata
18 Jan 2010, 3:51 PM
Hi Gjslick i just finish to implement a .net router that allow you to use Direct function with named params, just like you ask.
In fact, you will be able to call a Direct function in this way:

Example:


Aral.DiskManager.GetFiles({
path: '\\ext-3.1.0',
filter: '*.*',
},
function(result){
console.log(Ext.encode(result));
}
);and this is my response:


[{"fullName":"\ext-3.1.0\src\adapter","name":"adapter","modified":"20/12/2009 16:51:48","isFolder":true,"size":102901},{"fullName":"\ext-3.1.0\src\core","name":"core","modified":"20/12/2009 16:51:48","isFolder":true,"size":390820},{"fullName":"\ext-3.1.0\src\data","name":"data","modified":"20/12/2009 16:51:49","isFolder":true,"size":299148},{"fullName":"\ext-3.1.0\src\dd","name":"dd","modified":"20/12/2009 16:51:49","isFolder":true,"size":158051},{"fullName":"\ext-3.1.0\src\direct","name":"direct","modified":"20/12/2009 16:51:49","isFolder":true,"size":33234},{"fullName":"\ext-3.1.0\src\locale","name":"locale","modified":"20/12/2009 16:51:49","isFolder":true,"size":345111},{"fullName":"\ext-3.1.0\src\state","name":"state","modified":"20/12/2009 16:51:49","isFolder":true,"size":9665},{"fullName":"\ext-3.1.0\src\util","name":"util","modified":"20/12/2009 16:51:49","isFolder":true,"size":211035},{"fullName":"\ext-3.1.0\src\widgets","name":"widgets","modified":"20/12/2009 16:51:49","isFolder":true,"size":1551820},{"fullName":"\ext-3.1.0\src\.DS_Store","name":".DS_Store","modified":"20/12/2009 16:51:48","isFolder":false,"size":6148},{"fullName":"\ext-3.1.0\src\debug.js","name":"debug.js","modified":"20/12/2009 16:51:48","isFolder":false,"size":27240}]In this way all the files inside my Ext folder has been returned by my Direct function Call.

I also add some extra information to the generated API.
Check it out:


Ext.app.REMOTING_API = {"type":"remoting","url":"/modules/aral-disk-manager/server-scripts/DiskManager.ashx","namespace":"Aral","actions":{"DiskManager":[{"name":"GetFiles","len":2,"params":[{"name":"path","type":"string","pos":0},{"name":"filter","type":"string","pos":1}]}]}};As you can see i add a params array wich contains all the params accepted my the Direct method you are going to call with all the information you need like name, type and param position.
I just need a couple of days to clear a little bit the source code.
What do you think about that?

Gjslick
19 Jan 2010, 1:18 PM
Hey Andrea. Thanks for your reply.

Although, after not receiving any responses to this thread (or anywhere else that I posted about it), I kind of took matters into my own hands for the time being until an actual implementation was made. I guess that I should have just posted it, but I ended up getting busy and forgot about this thread.

What I did was I tried to take the simplest route to allow this ability, that would:


provide the ability to call Direct functions as usual (so I wouldn't have to change existing code), and
provide the ability to call that same Direct function with the parameters provided in a hash object -- both with explicit Direct calls, and with using a directFn and paramsAsHash: true on DirectProxy (i.e. DirectStore).


Basically the simplest way I could figure out to do this was to override RemotingProvider, to add a new function for every remoting method that gets created. So what happens is, every remoting method in my API gets an extra function: [remoteMethod]_withParamsAsHash(). It's not a perfect solution (and kind of a wordy one in fact), but it does the job nicely.


So here's an example of how I call it:


Ext.ss.MyClass.myMethod_withParamsAsHash( {
param1: 'value1',
param2: 'value2'
}, myCallback, myScope );
What this new function actually does is send the parameters in the format of how the Direct specification says it's going to send them when they actually implement it. In other words, the "data" of a Direct call to the router just has the object literal syntax of the data in there, instead of being wrapped in an array.

Data sent normally (even with paramsAsHash: true on a DirectProxy):

data: [ { param1: 'value1', param2: 'value2' } ]Data sent now with the new function:

data: { param1: 'value1', param2: 'value2' }So on the server side (I'm running ColdFusion), I added a bit of code to my stack to test if the data provided is an array, or a struct (object). If it's a struct, ColdFusion can automatically match up struct key names to arguments of a function/method, and that's what I have it do. If it's an array, it goes in the argument order as usual. (Anyone looking for a ColdFusion stack that can do this btw: http://www.extjs.com/forum/showthread.php?t=87640)


Here's my override to add the new function. It's relatively simple, and doesn't interfere with existing code. Lines in red are lines added to the original source.


/**
* Call remoting method "With Params As Hash" Override to RemotingProvider
* Works currently with Ext 3.1.0
*
* Creates another function for remoting called: [originalMethodName]_withParamsAsHash
* Takes 3 arguments:
* 1) the params object (key-value pairs)
* 2) the callback
* 3) the scope of the callback
*
* Ex:
* Ext.ss.MyClass.myMethod_withParamsAsHash( { param1: 'hi', param2: 'hello' }, myCallback, myScope );
*
*
* Can also be used with DirectStores (or any store configured with a DirectProxy) with the
* paramsAsHash config set to true (which it is true by default).
*
* Ex:
* var myStore = new Ext.data.DirectStore( {
* directFn: Ext.ss.MyClass.myMethod_withParamsAsHash,
* paramsAsHash: true
* } );
*
*/
Ext.override( Ext.direct.RemotingProvider, {

// Override
initAPI : function(){
var o = this.actions;
for(var c in o){
var cls = this.namespace[c] || (this.namespace[c] = {}),
ms = o[c];
for(var i = 0, len = ms.length; i < len; i++){
var m = ms[i];
cls[m.name] = this.createMethod(c, m);

// "withParamsAsHash" function.
// This new function will take 3 arguments, as described in the header of this file.
if( !m.formHandler )
cls[ m.name + '_withParamsAsHash' ] = this.createMethod( c, m, /* paramsAsHash */ true );
}
}
},


// Override
createMethod : function(c, m, paramsAsHash ){
if( !Ext.isDefined( paramsAsHash ) )
paramsAsHash = false;

var f;
if(!m.formHandler){
f = function(){
this.doCall(c, m, Array.prototype.slice.call(arguments, 0), paramsAsHash);
}.createDelegate(this);

}else{
f = function(form, callback, scope){
this.doForm(c, m, form, callback, scope);
}.createDelegate(this);
}

f.directCfg = {
action: c,
method: m
}

return f;
},


// Override
doCall : function( c, m, args, paramsAsHash ) {
if( paramsAsHash ) {
// paramsAsHash method expects 3 arguments: args object, callback, and scope
var data = args[ 0 ],
hs = args[ 1 ],
scope = args[ 2 ] || window;

} else {
var data = null, hs = args[m.len], scope = args[m.len+1];

if(m.len !== 0){
data = args.slice(0, m.len);
}
}

var t = new Ext.Direct.Transaction( {
provider: this,
args: args,
action: c,
method: m.name,
data: data,
cb: scope && Ext.isFunction( hs ) ? hs.createDelegate( scope ) : hs
} );

if(this.fireEvent( 'beforecall', this, t ) !== false){
Ext.Direct.addTransaction( t );
this.queueTransaction( t );
this.fireEvent( 'call', this, t );
}
}

} );

---

Good luck with your .NET router that supports the named arguments though. Unfortunately I'm really not up on the implementation details in creating one for .NET, as I have pretty limited .NET experience and don't use it in day-to-day development. But I'd definitely like to see what you came up with for the implementation of your API description on the client side.

-Greg