A client asked for help with invoking a jQuery ajax function during the submit of a Formidable Pro form. The client had written an elaborate jQuery routine that was triggered in $(document).on('submit'). The goal for the ajax call was to retrieve a confirmation number from a database. The ajax function needed to pass the values from the form's data entry fields to the processing script on the server. This is why the developer chose to use document on submit. When the confirmation number is returned from the server to the client, the value is written to a hidden field on the form as well as a display element on the form's success page. When saved, a PDF version of the form was created with the FormidablePro2PDF plugin and made available for download through a link on the form's success page.
This is a complex process and the results were very inconsistent. The confirmation always displayed on the success page, but almost never got written to the form entry in the database nor would it display on the PDF version of the form. We were tasked to figure out what was happening.
Had we been contracted to write the code in the first place, we probably would have opted to use Formidable Pro's built-in hooks, such as frm_pre_create_entry or something else that fires before the data is written to the database. But since, jQuery/Ajax was chosen as the vehicle to complete this process, we needed to fix it so it worked consistently.
To analyze this problem, it is critical to understand two important concepts:
This brings us to our second key concept. When we think of a browser, we may think of it in terms of the browser engine such as Blink, EdgeHTML, Gecko, or Webkit, but browsers are actually composed of multiple engines. Take a look at the reference architecture diagram from Reference Architecture for Web Browsers by Alan A. Grosskurth and Michael W. Godfrey from the School of Computer Science, University of Waterloo in Canada:
Some of the browser's components are:
- The user interface—this includes the address bar, back/forward button, bookmarking menu etc. Every part of the browser display except the main window where you see the requested page.
- The browser engine—the interface for querying and manipulating the rendering engine.
- The rendering engine—responsible for displaying the requested content. For example, if the requested content is HTML, it is responsible for parsing the HTML and CSS and displaying the parsed content on the screen.
- Networking—used for network calls, like HTTP requests. It has a platform independent interface and substructure implementations for each platform.
- UI backend—used for drawing basic widgets like combo boxes and windows. It exposes a generic interface that is not platform specific. Underneath it uses the operating system user interface methods.
- Data storage—This is a persistence layer. The browser needs to save all sorts of data on the hard disk, like cookies for example. The HTML5 specification defines this as a 'web database', which is a complete (although light) database in the browser.
The key to solving this timing issue is to prevent the form.submit() from firing until the networking engine has completed executing the HTTP GET request initiated by the ajax function. To do this we changed the trigger event from $(document).on('submit') to $("#btnSubmit").on( "click"). In the attached function, we immediately invoke e.preventDefault(), which stops the form.submit() from firing. We also needed to create a couple of callback functions for the done() and always() methods of the ajax object. The following code is a brief representation of the solution. We hope it helps with your own ajax related issues.