Marketing digital. Making results.

How to POST cross domain and access the returned data using ExtJS

Here is how to post data to a server on a different domain and receive data back using ExtJS (with inspiration from the GWT implementation).

First the FormPanel. The fields are standard and in the JS file we define two variables that are critical to making this work as they’ll allow us to keep track of what’s happening:

//These two variables are critical to the success of this operation    var xdm_formSubmitted = false;  var xdm_sameDomainRestored = false;  var renderDivId='myWidget';    var consigneeForm = new Ext.FormPanel(  {   id: 'customerWidget',   renderTo:renderDivId,  //By default, ExtJS uses XmlHttpRequest, this has to be a standard submit POST  standardSubmit: true,   url: 'http://www.iamonanotherdomain.com/addThisCustomerForMe',   border: false,   hideBorders: true,   items:  [  {   xtype: 'textfield',   name: 'customerFirstName'   },  {   xtype: 'textfield',   name: 'customerLastName'   }    ],    bbar:  [  //This is where the form post is triggerd  {   xtype: 'tbspacer',   width: 300  } ,    {   text: 'Save',   handler: function()    {   var form = Ext.getCmp('customerWidget').getForm();   form.getEl().dom.target=iframePostContainerName;   //On Submit we set this variable to true, you'll understand why in the event handler function   xdm_formSubmitted = true;   form.submit();  }  }  ]  

Notice that before submitting, we are assigning the target of the post to an iframe that exists on the page (form.getEl().dom.target=iframeName). This is the second and crucial step of the process. The iframe we are using is defined in the same js file:

  //This hidden iframe is used to receive the results of the form POST:    {   hidden: true,   renderTo:'myHiddenIFrame',   html:'<iframe id="' +iframePostContainerName + '" name="' +iframePostContainerName+ '"   onload=\"setupIFrameOnLoad(\'' + callbackFunction +  '\')"></iframe>'    }  //The callbackFunction variable is passed to the script by the calling page.    

Which brings us to the third critical piece of the process which is to attach an event handler function to the onload event of the iframe, and this is where all the magic will happen. As you can see i’ve name my event handler function setupIFrameOnLoad and here is the definition:

  setupIFrameOnLoad = function()  {   //If the form was submitted and we have loaded data from our own domain, we are good. Thank you for coming   //and here is your data! It's gonna be 5 dollars, Thank you!   if(xdm_formSubmitted && xdm_sameDomainRestored)   {        //You can access your data now using the window.name property, but        //I've got other plans in my callbackFunction so until such time...        var callbackFunctionCall = callbackFunction + "()";        eval(callbackFunctionCall);   }   //If this is the initial response from the POST, we are still in the POST server's domain   else if(xdm_formSubmitted && !xdm_sameDomainRestored)   {         //Now you know we're about to restore the local domain right?         xdm_sameDomainRestored = true;         //localResourceUrl is passed by the calling page and points to a local 1px image or empty page         document.getElementById(iframeName).contentWindow.location = localResourceUrl;   }   else   {         return ;   }  }    

What is happening here is basically the solution to the cross-domain issue in being able to pass data back to the calling page. Once your form is submitted, the response will be posted back to your iframe within your form page. Since the response is coming back from the server, security on the browser will keep us from accessing any of the properties on the window. To be able to access the data in window.name(which could be in JSON format if you wanted), the solution is simply to load a local resource file from your environment. It could be a simple blank 1px image or an empty HTML file, anything really to switch the iframe’s source content to be on the same domain where you are calling from. Once the iframe has reloaded you can simply access your data in the window.name property. To close the cycle, the response from your server needs to be a script which sets the window.name property. Using Spring, here is how my action was set up:

</pre>  private void addThisCustomerForMe(HttpServletRequest req, HttpServletResponse response) throws Exception  {    Long customerId = customerController.addOrUpdateCustomer(req);  response.setContentType("text/javascript");  OutputStreamWriter os = new OutputStreamWriter(response.getOutputStream());  StringBuffer buf = new StringBuffer("");  buf.append("<html>");  buf.append("<script type=\"text/javascript\">");  buf.append("  window.name="+customerId+";");    // can set json data here if you want  buf.append("</script>");  buf.append("</html>");    os.write(buf.toString());  os.flush();  os.close();    }