I have a form which when submitted is processed via jQuery ajax call to a PHP script.
The 1st time the form is submitted, jQuery catches the event, runs the ajax call and PHP script and returns the data from the PHP script putting it in the required HTML elements.
However, if the submit button is pressed a 2nd time, the form is submitted normally and jQuery is unable to "preventDefault" so to speak. So the whole page is reloaded.
the jQuery code
$(document).ready(function() {
// catch form submittion
$('#user_account_form').submit(function(ev) {
// prevent default action and propagation
ev.preventDefault();
ev.stopPropagation();
// pull data from the form attributes
var href = $(this).attr('action');
var postData = $(this).serializeArray();
// run the ajax call
var request = $.ajax({
url: "view/jquery/" + href,
type: "post",
data: postData,
dataType: "json"
});
// ajax call completed?
// -- echo returned data to elements
request.done(function(data) {
// put the refreshed form (provided by PHP script) in the #user_account element
$('#user_account').html(data.form);
// put the system message (provided by PHP script) in the #sysmsg element
$('#sysmsg').html(data.sysmsg).delay(2000).fadeOut(100);
});
// on fail, log to console
request.fail(function(jqXHR, textStatus, errorThrown) {
console.log('error processing form data: ' + textStatus + " [" + errorThrown + "]");
});
});
});
the PHP code
this is basically a simple script that checks the entered data from the form
against the data in the database. If the entered password equals the database
password the database is updated, otherwise it will only return a system message
to the user that the password was incorrect.
I believe the fault is that I'm missing something in my jQuery code that makes jQuery catch the 2nd, 3rd, 4th, etc. submission.
Try:
$('#user_account_form').on('submit', function(ev) {});
Instead of:
$('#user_account_form').submit(function(ev) {});
This is because as I understood, your submit button is in the data that is refresh from the back end, which means that the button is not bound to any events as it's a completely new button. jQuery on will bind the event to all instances of that element, even if they are created in the future.
Important: If you use jQuery < 1.7, instead of on() use live().
Maybe try to use a counter so you'll know how many time you've clicked on your submit btn
$(document).ready(function() {
var counter = 0;
// catch form submittion
$('#user_account_form').submit(function(ev) {
// If first click
if(counter === 0){
// Do the preventDefault and ajax thing
}
else{
// Do nothing or what you expect for a >2nd click
}
// Increment counter
counter++;
})
});
After reading your posts about the PHP script building a completely new form and therefore not binding the submit button preventing jQuery from catching subsequent submissions, I figured "Why build a whole new form if I only need to refresh 1 or 2 fields?".
So I changed my PHP script to return only the data from the database of the changed fields and send that in a json format to my jQuery script. Then adjusted my jQuery script to read the json object, and put the new values into the corresponding fields.
Now it works as intended.
changed jQuery code
....
request.done(function(data) {
$('#email').val(data.email);
$('#sysmsg').html(data.sysmsg).delay(2000).fadeOut(100);
});
changed PHP code
....
$email = $main->getUserDetails('email');
$array = array("sysmsg" => $msg, "email" => $email);
$data = json_encode($array);
echo $data;
Thanks for your input all, it helped me figuring out what to change to improve my code.
Related
I already checked around for this answer but all are different problems just same title (to prevent random duplicate marks).
Here is an ajax call to the click of the filter button that should send the data inserted in the form formmatcat to the php file formfilt.php and should load the result in a div with id resultins
<script>
$(function () {
$('#filter').on('click', function(event){
event.preventDefault();
$.ajax({
type: 'post',
url: 'formfilt.php',
data: $('#formmatcat').serialize(),
success: function () {
$("#resultins").load('formfilt.php');
}
});
});
});
</script>
I set the preventdefault to load only in the div without redirecting to the php file and this works but if I put the preventDefault it echoes the string I build by concatenating values sent from the form with those empty values. The strange thing is that if I remove preventDefault of course it redirects and loads the php file but with the correct values:
Moral of the story, data in the form with the ajax call goes correctly to the php file but looks like preventDefault don't let this. Thanks in advance
Here's the structure of the html part with the form
<form id="formmatcat" method="post" action="formfilt.php">
.
.
various textboxes
.
.
</form>
What you're doing is sending an AJAX request toformfilt.php, when this call happens and it returns a response it will be stored as a parameter within the success or $.done function as I'll mention later, that is where your echo'd content will be.
What you're doing here is when the call is successful, you simple send a GET request to the same page. Since that GET request differs from the AJAX POST request and has no POST parameters you'll not get the correct output.
By simply submitting the form and letting it go to the page rather than cancelling the request you're getting the right values as you're directly posting to the page with the correct values, when you call the load function you're doing a seperate AJAX get request.
What load actually is, is a rough equivelant to $.get which is shorthand for $.ajax.
Looking at jQuery AJAX docs
jqXHR.done(function( data, textStatus, jqXHR ) {});
An alternative construct to the success callback option, the .done() method replaces the deprecated jqXHR.success() method. Refer to deferred.done() for implementation details.
Basically, a $.ajax() call returns a promise object that you can chain callbacks on when it is finished. Also note that data here will be the actual content within your PHP file, thus if you rewrite your AJAX call like so:
<script type="text/javascript">
$(function() {
$('#filter').on('click', function(e) {
e.preventDefault();
$.ajax({
type: 'post',
url: 'formfilt.php',
data: $('#formmatcat').serialize()
}).done(function(data) {
$('#resultins').html(data);
});
});
});
</script>
It will then continue to load the output of formfilt.php into the div with ID resultins.
dont use form, use input without form, and use button tag use onclick to run function, if you use form, it will submit and redirect,
i'm not good with ajax on jQuery
but if i were to use javascript/XHR
var CB=document.getElementById("filter").value; //get input/filter value
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200)
document.getElementById('contain').innerHTML=xhttp.responseText;
};
var url="formfilt.php?filter="+CB;
xhttp.open("GET", url, true);
xhttp.send();
if you want to use post :
xhttp.open("POST", "formfilt.php", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send('filter='+CB);
sorry, i'm also learning, and new to this, just learning a week ago,
I have a form and when the user clicks the submit button I want to run a separate PHP script before the form-action (going to the next page) gets executed.
Of course I can stop the form-action with evt.preventDefault(); and then I can fire my jquery $.post call but then I cannot 'resume' or undo this preventDefault call, as far as I can see.
So what is the best way to execute a script that process some information after a user clicks the submit button BUT before the user gets redirected to the next page defined in the form action tag?
(Of course I could just carry over the data and perform whatever I want on the next page – but in this case, I would like to keep it separate).
Thanks for any suggestions!
You can try something like this:
var posted = false;
$('form').on('submit', function(ev) {
if ( ! posted ) {
ev.preventDefault();
$.post(url).done(function() {
posted = true;
$('form').trigger('submit');
});
}
posted = false;
});
Or more succinct, using extra parameters:
$('form').on('submit', function(ev, posted) {
if ( ! posted ) {
ev.preventDefault();
$.post(url).done(function() {
$('form').trigger('submit', [true]);
});
}
});
Your $.post call can be run synchronously, so the form would not submit until you've got a response from the server.
You can submit the form programmatically, perhaps in your callback function.
prevent default on form, then run post, on success of post, target the form by id and use .submit();
$('#submit-button').click(function(e) {
e.preventDefault();
$.post({
url:'url',
success:function() {
$('#formid').submit()
}
});
});
Go head with your evt.preventDefault().
Make an $.ajax() call to run your php script.
In the $.ajax() success/failure callback, check the output of the php script you want to run, and accordingly make a $.post call (or not).
You can always hook the click event, and do your stuff.
When you are done you just do $(form).submit();
Working example
$("#submitbutton").click(function(e) {
e.preventDefault();
// do your ajax stuff here.. $.post().
$("#form").submit();
});
You can use just use the native submit function instead of jQuery's submit() which goes through the event handler again
$('form').submit(function(e){ // change form to your form id
e.preventDefault();
var el = this; // store this form in variable
$.post('/echo/html/',data,function(d){ // your post function
el.submit(); // trigger native submit function in success callback
});
});
FIDDLE
In your form tag, add onsubmit="myfunction()"
I use a page with Jquery tabs and if i submit one of the forms in the tabs only that tab is submitted and refreshed with this jquery code:
$(document).on("submit", "#plaatsen_stap3", function(event) {
/* stop form from submitting normally */
event.preventDefault();
$.ajax({
type:"GET",
url:"../plaatsen_advertentie/plaatsen_advertentie_stap3.php",
cache: false,
data: $("#plaatsen_stap3").serialize(),
success:function(data){
$("#tab2").html(data);
}
});
});
But in the case that there has to be payed i want to reload the page with the payment page. I want to do that AFTER the div is reloaded with the data, because i need to put a payment row in the DB with the data from the GET. Is location an option? If i use that now only the div (tab2) is loaded with the payment page....
So:
1.push submit
2.submit the form and load page/script in div by Ajax
3.check in php script (within the div) if payment is needed
4.if yes,add row with payment data in database and reload entire page with payment page (with some Get data in the url (last inserted id)
success:function(data){
$("#tab2").html(data);
location.href = "/yourpage.php";
}
Since you wanna do once the HTML is generated, give some time like about 5 seconds?
success:function(data){
$("#tab2").html(data);
setTimeout(function(){location.href = "/yourpage.php";}, 5000);
}
This would work for your use case. This cannot be done from server side.
I think load() is what you are looking for. http://api.jquery.com/load/
The code below is intended as a guideline, and I'm not even sure it's working (I have not tested it). But I hope it will be of some help.
I would do something like this:
//Step 1
$(document).on("submit", "#plaatsen_stap3", function(event) {
/* stop form from submitting normally */
event.preventDefault();
$.ajax({
type:"GET",
url:"../plaatsen_advertentie/plaatsen_advertentie_stap3.php",
cache: false,
data: $("#plaatsen_stap3").serialize(),
success:function(data){
//Step 2 - submit the form and load page/script in div by Ajax
//Make sure array[] is an actual array that is sent to the test.php-script.
$("#tab2").load("test.php", { 'array[]' , function() {
//Step 3 - check in php script (within the div) if payment is needed (Do this from test.php - don't check the actual div but check values from array[])
//Step 4 - if yes,add row with payment data in database and reload entire page with payment page (with some Get data in the url (last inserted id)
//Do this from test.php and use header-redirect to reload entire page
$("tab2").html(data); //Do this when test.php is loaded
}
} );
}
});
});
I have what I think is a fairly classical problem involving what looks to me like a callback race, but in spite of all my reading, I'm still stuck. You'll find the code pasted below.
It's a simple log in form and you can see that when a certain button is clicked, I'll send the form data "ajaxically" to an external php file. Once the php has run, I'm to receive the results back, and as a test here, to simply alert out the email address from the php file.
When I run this, the ajax callback doesn't execute. If I click the button fast and repeatedly, I get the right alert. I also get the right response if I put in an extra alert.
How do I get it to run without doing these other silly things?
Thanks in advance
RR
$('#'+this.loginForm[0].parentId+"logIn")
.on('click', function() {
var jax = $.ajax(
{
type: "POST",
url: "../sharedfunctions3/act-membership.php",
data: {email: document.getElementById(that.parentId+'email').value,
password: document.getElementById(that.parentId+'password').value,
path: that.path,
action: "logIn"
}
});
jax.done(function()
{
obj = JSON.parse($.trim(jax.responseText));
alert(obj.email);
});
jax.fail(function() { alert("error"); });
alert(1);
});
I had a hunch that when you clicked the button the browser was submitting synchronously and asynchronously.
The return false; tells the browser to not submit the form and to prevent default actions from there on.
When a button inside of a form tag is clicked, most browsers will submit the form even though it is not a submit input.
I am trying to write a script that will submit all the individual forms on a single page.
I start by counting the amount of forms, then using that count I iterate through each form and submit it.
On the PHP page each form is written like so:
<form name="order_driver_'.$j.'" class="order_container" id="save_'.$j.'"method="post" action="../scripts/order_driver_save.php">
I then use JavaScript to count each one and submit them:
function count_form(){
//Count the amount of outputs
var count = $(".order_container").size();
//Run loop for reults
for(count=count;count>0;count--){
//var save='order_driver_'+count;
document.order_driver+count.submit();
}
}
The issue I have is in the submit part:
document.order_driver_ + count.submit();
I can't concatenate the var count to the .order_driver_.
I am wondering how to do this so I can specify each form name to be submitted in the loop.
You are going to have to submit them via AJAX if you want them to all submit, because as soon as one is submitted, the browser will follow the request, and refresh the page. So even if you got it to concatenate, it would only submit the first.
UPDATE
While I know i might get blasted by suggesting you use jquery, I think in this situation, it greatly simplifies what you need to do.
this code will accomplish your goal if you use jQuery.
// #submit-click being whatever you want to initiate the mass form submit
$('#submit-button').click(function() {
$('form').submit();
});
//form submit event handler
$('form').submit(function() {
//get the form and serialize it's data
var form = $(this);
var data = form.serialize();
//submit via AJAX
$.post(form.attr('action'), data);
//prevent the default action of submit
return false;
});
notice that you will receive no confirmation that they have been submitted.
Note: you're going to have to make the calls separate from each other or the page will move to the target of the submit. Either Ajax calls or make the target be in a new window.
Change it to get the element and submit that element:
function count_form(){
//Count the amount of outputs
var count = $(".order_container").size();
//Run loop for reults
for(count=count;count>0;count--){
//var save='order_driver_'+count;
document.getElementById("order_driver_" + count).submit();
}
}