Reputation: 1148
I'm trying to make 2 requests on Submit action in a form.
1 request is sent to an external DB using an external script.
The other request however is an AJAX POST request which stores the form fields in localStorage and posts the JSON to a PHP file which then saves the data to a text file on the current server (where the form is hosted)
The issue is that the AJAX POST request gets cancelled on submit because the 1st action (external script sending data to external DB) navigates away from the current page and gives you a success/failure status of the submission.
I know this because there is a form validation in place (which doesn't stop the AJAX request) and if there is a validation error in email, the form doesn't navigate to another page but the AJAX POST request is successful and JSON data is delivered properly to the text file on the server.
Following is the HTML/JS and PHP code:
HTML/JS:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="eloqua.css">
<script src="http://code.jquery.com/jquery-1.9.0.js"></script>
<script type="text/javascript">
$(document).ready(function(){
localStorage.clear();
$("form").on("submit", function() {
if(window.localStorage!==undefined) {
var fields = $(this).serialize();
localStorage.setItem("eloqua-fields", JSON.stringify( fields ));
$.ajax({
type: "POST",
url: "backend.php",
data: fields
});
} else {
alert("Storage Failed. Try refreshing");
}
});
});
</script>
<script type="text/javascript">
function validateForm()
{
var a=document.forms["EloquaForm"]["C_FirstName"].value;
if (a==null || a=="")
{
alert("First name must be filled out");
return false;
}
var b=document.forms["EloquaForm"]["C_LastName"].value;
if (b==null || b=="")
{
alert("Last name must be filled out");
return false;
}
var y=document.forms["EloquaForm"]["C_EmailAddress"].value;
var atpos=y.indexOf("@");
var dotpos=y.lastIndexOf(".");
if (atpos<1 || dotpos<atpos+2 || dotpos+2>=y.length)
{
alert("Not a valid e-mail address");
return false;
}
}
</script>
</head>
<body>
<p><img src="red-asterix.jpeg"> indicates a required field</p>
<div class="form-container" style="width: 625px">
<form class="form-eloqua" name="EloquaForm" action="http://s33.t.eloqua.com/e/f2" onsubmit="return validateForm();" method="post">
<span class="form-eloqua-label"><span>First Name</span></span><input id="firstname" type="text" name="C_FirstName" />
<span class="form-eloqua-label"><span>Last Name</span></span><input id="lastname" type="text" name="C_LastName" />
<span class="form-eloqua-label"><span>Email Address</span></span><input id="email" type="text" name="C_EmailAddress" />
<span class="form-eloqua-label">Title</span><input id="title" type="text" name="C_Title" />
<span class="form-eloqua-label">Company</span><input id="company" type="text" name="C_Company" />
<span class="form-eloqua-label">ZIP or Postal Code</span><input id="postcode" type="text" name="zipOrPostalCode" />
<span class="form-eloqua-label">Country</span><select id="country" name="country">
<option value="">Please select ...</option>
<option value="AF">Afghanistan</option>
<option value="AL">Albania</option>
<option value="DZ">Algeria</option>
<option value="AS">American Samoa</option>
<option value="AD">Andorra</option>
<option value="AG">Angola</option>
<option value="AI">Anguilla</option>
<option value="AG">Antigua & Barbuda</option>
<option value="AR">Argentina</option>
<option value="AA">Armenia</option>
<option value="AW">Aruba</option>
<option value="AU">Australia</option>
<option value="AT">Austria</option>
<option value="AZ">Azerbaijan</option>
<option value="BS">Bahamas</option>
<option value="BH">Bahrain</option>
<option value="BD">Bangladesh</option>
<option value="BB">Barbados</option>
<option value="BY">Belarus</option>
<option value="BE">Belgium</option>
<option value="BZ">Belize</option>
<option value="BJ">Benin</option>
<option value="BM">Bermuda</option>
<option value="BT">Bhutan</option>
<option value="BO">Bolivia</option>
<option value="BL">Bonaire</option>
<option value="BA">Bosnia & Herzegovina</option>
<option value="BW">Botswana</option>
<option value="BR">Brazil</option>
<option value="BC">British Indian Ocean Ter</option>
<option value="BN">Brunei</option>
<option value="BG">Bulgaria</option>
<option value="BF">Burkina Faso</option>
<option value="BI">Burundi</option>
<option value="KH">Cambodia</option>
<option value="CM">Cameroon</option>
<option value="CA">Canada</option>
<option value="IC">Canary Islands</option>
<option value="CV">Cape Verde</option>
<option value="KY">Cayman Islands</option>
<option value="CF">Central African Republic</option>
<option value="TD">Chad</option>
<option value="CD">Channel Islands</option>
<option value="CL">Chile</option>
<option value="CN">China</option>
<option value="CI">Christmas Island</option>
<option value="CS">Cocos Island</option>
<option value="CO">Colombia</option>
<option value="CC">Comoros</option>
<option value="CG">Congo</option>
<option value="CK">Cook Islands</option>
<option value="CR">Costa Rica</option>
<option value="CT">Cote D'Ivoire</option>
<option value="HR">Croatia</option>
<option value="CU">Cuba</option>
<option value="CB">Curacao</option>
<option value="CY">Cyprus</option>
<option value="CZ">Czech Republic</option>
<option value="DK">Denmark</option>
<option value="DJ">Djibouti</option>
<option value="DM">Dominica</option>
<option value="DO">Dominican Republic</option>
</select>
<div class="form-eloqua-separator"></div>
<span class="form-eloqua-label">Annual Revenue Range</span><select name="C_Annual_Revenue1"> <option value="">Please select ...</option> <option value="0-100,000,000">0-100,000,000</option><option value="100,000,001-300,000,000">100,000,001-300,000,000</option><option value="300,000,001-500,000,000">300,000,001-500,000,000</option><option value="500,000,001-2,000,000,000">500,000,001-2,000,000,000</option><option value="2 Billion +">2 Billion +</option></select>
<div class="submit-button"><input type="submit" id="submit" value="Submit" /></div>
<div id="output"></div>
<input type="hidden" name="elqoffer" value="GGB2BContentMktg" />
<input type="hidden" name="elqchannel" value="TheMarketer" />
<input type="hidden" name="elqbq" value="14Q2" />
<input type="hidden" name="elqbc" value="UK" />
<input type="hidden" name="elqFormName" value="2013-Syndication-1372365875136" />
<input type="hidden" name="elqSiteId" value="33" />
</form>
</div>
</body>
</html>
PHP:
<h1>Below is the data retrieved from SERVER</h1>
<?php
date_default_timezone_set('America/Chicago'); // CDT
echo '<h2>Server Timezone : ' . date_default_timezone_get() . '</h2>';
$current_date = date('d/m/Y == H:i:s ');
print "<h2>Server Time : " . $current_date . "</h2>";
$file_content = array();
if ( file_exists('your_data.txt')){
$file_content = (array)json_decode(file_get_contents('your_data.txt'));
unlink('your_data.txt');
}
$file_content['users'][] = array('user'=>$_POST);
file_put_contents('your_data.txt',json_encode($file_content));
?>
LIVE VERSION of the form: http://bhanuchawla.me/dev/redactive/marketerform/
Text file where JSON data is posted: http://bhanuchawla.me/dev/redactive/marketerform/your_data.txt
NOTE: if you get a Submission Successful message when you submit the form, it means that the external script on action ran successfully and not the AJAX. To test if data is submitted via AJAX check out the your_data.txt file (URL above)
How do I make sure that AJAX POST is done before the page navigates away?
Upvotes: 0
Views: 1563
Reputation: 451
Do a form.submit() after your ajax request is completed. According to https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement.submit() it should bypass your event handler and get you your desired result.
var isSubmitted = false;
$(document).ready(function(){
localStorage.clear();
$("form").on("submit", function(evt) {
if (!isSubmitted) {
evt.preventDefault();
var $this = $(this);
if(window.localStorage!==undefined) {
var fields = $(this).serialize();
// Not an async task so don't need promise.
localStorage.setItem("eloqua-fields", JSON.stringify( fields ));
$.ajax({
type: "POST",
url: "backend.php",
data: fields
}).done(function() {
isSubmitted = true;
$this.submit();
});
} else {
alert("Storage Failed. Try refreshing");
}
return false;
} else {
return true;
}
});
});
This is untested, so not sure if it will work properly. Although, this is a fairly convoluted way of handling things. In my head, doing an AJAX request + POST Form submit feels wrong. I'd say stick to doing 2 AJAX requests(including form submit).
Upvotes: 1
Reputation: 4657
if you change this
$("form").on("submit", function() {
if(window.localStorage!==undefined) {
to
$("form").on("submit", function(e) {
e.preventDefault();
if(window.localStorage!==undefined) {
this will prevent the form from being submitted naturally...
!update: forgot to pass the event to the function! code updated.
http://api.jquery.com/event.preventdefault/
Upvotes: 1
Reputation: 2004
If you want to wait till both the ajax requests finish, you can make use of jquery deferred objects. That way, you can redirect to the other page only when both the request have been complete. Below is the simple sample code to use deferred objects.
var fn1 = $.ajax("/url-1.php");
var fn2 = $.ajax("/url-2.php");
$.when(fn1, fn2).done(function(fn1, fn2) {
alert("all complete");
});
Upvotes: 1
Reputation: 5764
When I get you right, your problem is based on the fact, that you want to do two totally different things after one submit. You could do this on a few ways.
Variant one: No Ajax, Post your Data, do whatever you do in backend.php and then use curl to send post data to the other server.
Variant two: In case you want to do this with ajax, you could try it this way:
// this is your old anonymus function a bit modified...
var ajaxSubmitHandler = function(e) {
e.preventDefault();
if(window.localStorage!==undefined) {
var fields = $(this).serialize();
localStorage.setItem("eloqua-fields", JSON.stringify( fields ));
$.ajax({
type: "POST",
url: "backend.php",
data: fields,
// and when ajax is done ... remove the event handler
done : function() {
// deactivate submit handler....
$("form").off("submit", ajaxSubmitHandler);
// and simply retrigger the submit
// this time it will only do the normal action
$("form").submit();
}
});
} else {
alert("Storage Failed. Try refreshing");
}
}
// per default you use the handler with the nested ajax request
$("form").on("submit", ajaxSubmitHandler);
Upvotes: 1
Reputation: 195
make a sync call to your php page by passing 'async:false' in your ajax call
$.ajax({
type: "POST",
async:false;
url: "backend.php",
data: fields
});
Upvotes: 0