It's common to need to pass extra information to a callback method, but since all callback methods have only one parameter (the return code from the remote method) this can be tricky.
DWR addresses this problem with the addition of several optional attributes on the call meta-data object: arg, callbackArg, and exceptionArg.
For an alternative approach you may use a Javascript closure.
DWR allows for an argument to be specified and passed to handlers -- eliminating the need for JavaScript closures. This argument can apply to the callbackHandler the exceptionHandler, or both. In order to take advantage of this feature you must use a call meta-data object (Call meta-data is explained in the scripting introduction).
var dataFromBrowser = ...; var callMetaData = { callback:callbackFunction, arg: dataFromBrowser // specify an argument to pass to the callback and exceptionHandler }; Remote.method(params, callMetaData); function callbackFunction(dataFromServer, arg1) { // you will now have access to dataFromBrowser as arg1 }Rules:
var dataFromBrowser = ...; var dataFromBrowser2 = ...; var callMetaData = { callback:callbackFunction, arg: dataFromBrowser, // specify an argument to pass to the exeptionHandler callbackArg: dataFromBrowser2, // overrides args will be passed to the callback exceptionHandler: exceptionHandlerFunction }; Remote.method(params, callMetaData); function callbackFunction(dataFromServer, arg1) { // you will now have access to dataFromBrowser2 as arg1 // callbackArg overrides arg } function exceptionHandlerFunction(exceptionMessage, exception, arg1) { // you will now have access to dataFromBrowser1 as arg1 // arg also applies to exceptionHandlers }
DWR also addresses scope issues within callback and exception handlers. We have added several optional attributes on the call meta-data object: scope, callbackScope, and exceptionScope.
(function() { someObject = {}; someObject.privateVar = "Private variable from the main object."; someObject.callbackFunction = function(dataFromServer) { alert(this.privateVar); // The preceding line will alert the value of privateVar. // The key here is the use of 'this'. The scope is not // lost because it is specified in the call-meta data object // and used to execute the callback function. } })(); var callMetaData = { callback:someObject.callbackFunction, scope: someObject }; Remote.method(params, callMetaData);Rules:
Note: The default scope is window.
A JavaScript closure is required to pass extra data to a callback or exception handler prior to the 3.0 release. For example, your callback method needs to look something like this:
function callbackFunc(dataFromServer, dataFromBrowser) { // do something with dataFromServer and dataFromBrowser ... }
Then you can arrange for this method to be called as follows:
var dataFromBrowser = ...; // define an erasure function to store a reference to // dataFromBrowser and to call dataFromServer var callbackProxy = function(dataFromServer) { callbackFunc(dataFromServer, dataFromBrowser); }; var callMetaData = { callback:callbackProxy }; Remote.method(params, callMetaData);
(Call meta-data is explained in the scripting introduction)
In other words the function that you pass as the callback is not the real callback - it's just a closure that acts as a proxy, to pass the data on having added in the client side data.
You could write this more succinctly as:
var dataFromBrowser = ...; Remote.method(params, { callback:function(dataFromServer) { callbackFunc(dataFromServer, dataFromBrowser); } });