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

Please refer to my earlier post for background on this project.

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();

}
Advertisements

5 thoughts on “How to POST cross domain and access the returned data using ExtJS

  1. is it possible to do this (copy document content to iframe name properti) using only standard javascript?
    or is “ext JS” a must?

  2. I would like to upload files to cross domain server from extjs using form.submit() method. When i call form.submit(), request is going to my restful web service and file is getting uploaded successfully. But the response is blocked at the browser with message: Blocked a frame with origi…host:1841″ from accessing a cross-origin frame.

    From older posts and form submit code, i found that doSubmit() is sending the Ajax request with out cors:true statement due to which cross domain response is blocked.

    I would like to follow your approach to get the response, so i have placed below code in my form panel as an item:
    {
    hidden: true,
    renderTo:’myHiddenIFrame’,
    html:”

    }

    Now ExtJS is giving this error: Cannot read property ‘dom’ of null
    and form is not getting loaded in UI.
    I am confused on where to keep the frame. I am using ExtJS5 and i have view and view controller defined.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s