Ok so I have a script that layers data throughout the process (an online test, data is kept for up to 50 questions). I have recently found that my Ajax and jquery code is not stopping all users from getting a secondary page that is meant to be reloaded in place of a DIV currently on the page. All information is passed through the jquery and ajax and works great, but sometimes on a users very first visit and first question it loads the page that is just meant to replace the DIV information currently and is not meant to be visible.
Here is my Ajax & jquery code:
<script>
$("#quizForm").submit(function(event){
event.preventDefault(); //prevent default action
var post_url = $(this).attr("action"); //get form action url
var form_data = $(this).serialize(); //Encode form elements for submission
$.post( post_url, form_data, function( response ) {
$("#prntqst").html( response );
dataLayer.push({"event" : "formSubmitted", "formName" : "'.$this->quizID.'"});
});
});
</script>
Here is the HTML:
<div id="prntqst"> <!-- this is DIV set to be reloaded -->
<font class="prntqst-text">Question Goes Here</font>
<form id="quizForm" action="ajax.php" method="post"> <!-- Script setup to handle submitted data -->
<input type="hidden" id="next_question" name="next_question" value="2">
<input type="hidden" id="quiz_type" name="quiz_type" value="learning">
<input type="hidden" id="quiz_name" name="quiz_name" value="knowledge-1">
<label class="container" for="a">Ans A
<input type="radio" name="answers[1]" id="a" value="a">
<span class="checkmark"></span>
</label>
<label class="container" for="b">Ans B
<input type="radio" name="answers[1]" id="b" value="b">
<span class="checkmark"></span>
</label>
<label class="container" for="c">Ans C
<input type="radio" name="answers[1]" id="c" value="c">
<span class="checkmark"></span>
</label>
<div class="subbtn_contain">
<div class="submitbtn">
<input id="submit" type="submit" class="button" value="Next Question">
</div>
</div></div>
</form>
<!-- currently this is the location of Ajax and jquery script -->
<div>
So when the form is submitted it processes the data through the ajax.php page, and then page reloads the next question into the "prntqst" DIV, after the first page load every request is sent to the ajax.php location, and all subsequent reloads carry all of the data needed for the test to work properly. However I find that if I use a new computer, or clear the cache the very first request can sometimes result in the user be pushed to the location of the ajax.php instead of them staying at the current URL with a DIV reload.
I have verified this issue through my analytics account, 99% of the time a user still shows at the correct URL as if the ajax is properly reloading the DIV, however sometimes it does show a user directly at the ajax.php script.
Any ideas or comments would be appreciated,
Thanks again!
Okay, I see now.
If you can have "some garbage" inside a code block and, as you say
works with or without that line...
That's because that code block is not even running at all.
The processData: false is a value assignation to an object property. It is ouside any object, in the code you provided. Then it seems like you tried to comment it like this: <!-- removed from code processData: false; -->, which also should throw an error. That is the HTML way to comment lines. in JS, it would be // removed from code processData: false;.
So... It seems that the form submits anyway. That just can the the "normal" form submit where the whole page reloads. As a test. Please try your page with that script completely removed. You should see no difference.
There is something else to explain here. You are playing with "dynamic" elements. Those are elements that didn't exist on page load and were added after... Or element that were there and were removed/replaced.
You have to write the script in such that this situation is handled.
In $("#quizForm").submit(function(event){ an event handler is attached to the element #quizForm. If there is no such element in the page when the page first load... Or there is a parsing error... The function won't run. So the event.preventDefault() won't be called either.
Then, assuming you fixed all errors in that code block and it runs. It squarely replaces all the HTML inside #prntqst. So for the second submit, the element on which the event handler was attached is not there anymore and the function won't run again.
The solution for that is to use event delegation to attach the event handler to the document and "delegate" it to the #quizForm (if exist when the handler is called).
That is $(document).on("event", "delegated_element_selector", function(){
So when the "event" fires within the "document", a lookup is made to find the "delegated_element_selector" and if found, the handler is executed.
That way is the way to have some event handler for the dynamic elements in a page.
Additionnally, about your question where to place the code, I added a $(document).ready() handler, which ensures the initial page load is complete before trying any jQuery lookup on some elements. So you can place that script where you want.
$(document).ready(function () {
$(document).on("submit", "#quizForm", function (event) {
console.log("Custom submit")
event.preventDefault(); //prevent default action
var post_url = $(this).attr("action"); //get form action url
var form_data = $(this).serialize(); //Encode form elements for submission
$.post(post_url, form_data, function (response) {
console.log(response)
$("#prntqst").html(response);
dataLayer.push({ event: "formSubmitted", formName: "'.$this->quizID.'" });
});
});
});
Now you should see "Custom submit" in the console on each form submit. And you should see what is the response too.
About post_url , I didn't any action attribute to the <form>... Maybe you just did not post it here on SO. Make sure there is one. Also make sure that the response $.post() should receive only is the necessary HTML and not a whole page (with <head>, <body>, etc...).
Related
I have this form:
<form method="post" action="/cart" id="ajax">
{...}
<div>
{{ product.option | hidden_option_input }}
</div>
<button name="submit" type="submit" title="add to cart">Add to Cart</button>
</form>
The form is being loaded to the page via ajax, and its action page also preloaded via ajax in a different link in the navbar. I'd like to submit the form but prevent it from opening a new page when submitted. How can I go about this? I've tried:
Add to Cart
to replace the button, but even though I've attempted to negate the default behavior with "return false;" it still reloads a new page on click. I can see the linked popup window just before the new page load, but it does not submit until the new page appears. I believe it's because the form is being loaded via ajax when a user clicks the link to it, therefore I cannot attach a script to it specifically because until it's on screen, it does not technically exist.
If I understand your question, you would like to just update a portion of the current page. If so, you will have to use AJAX for this:
Keep the "submit" button but make it a standard button and give it an id such as "submit":
<button id="submit" name="submit" title="add to cart">Add to Cart</button>
Then your JavaScript would handle the click event on the button as follows:
$(function() {
let submit = $('#submit');
submit.click( function() { //
submit.prop('disabled', true); // prevent a re-submission
var form = $('#ajax');
var request = $.ajax({
url: form.attr('action'), // get the action from the form
type: form.attr('method'), // get the method from the from
dataType: 'html', // the assumption is that we are dealing HTML here
data: form.serialize()
});
request.done(function(ajaxResult) {
// update the DOM with the results
$('#some_div').html(ajaxResult); // replace contents of <div id="some_div"></div> with new html
submit.prop('disabled', false); // re-enable the submit
});
});
});
You have to arrange for the results sent back to be just the HTML that is required to be updated.
Update
Since responding, you have added a comment with a link that suggests I may have misunderstood your intent. The phrase you used, "submit the form but prevent it from opening a new page when submitted" definitely can lead one to my original interpretation.
Have a Java based web application with a page where a feed of posts is dynamically generated with the help of JSTL. The user can currently 'like' any post in the feed but this has proved much more difficult to implement using AJAX. I know i'm really close here but can't quite figure out what's wrong.
It works but only for the first item in the array.. So any like button that is pressed in the feed, only updates the first like button in the feed. Why is it that the dynamically assigned div value (input name=likesDivCount) only registers the first assignment?
index.jsp
<c:forEach items="${idFeedArray}" var="posts" varStatus="count">
...feed item (such as image, text etc..)...
<form id="likesform" action="../AddLike" method="post" style="display:inline;">
// the value of this input below is supposed to change...(i.e. #likesSize0,#likesSize1,#likesSize2)
<input name="likesDivCount" value="#likesSize${count.index}" type="hidden">
<input name="postUser" value="${userpost[count.index]}" type="hidden">
// this button sends the AJAX request
<button style="padding-right: 0;" type="submit" class="btn btn-link"><span class="glyphicon glyphicon-thumbs-up"></span></button>
</form>
// The span in the button below updates with the response from the AJAX
<button style="padding-left: 0;" class="btn btn-link"><span id="likesSize${count.index}">${likesArraySize[count.index]}</span></button>
</c:forEach>
<script>
$(document).on("submit", "#likesform", function(event) {
var $form = $(this);
var likesDivCount = $("input[name=likesDivCount]").val();
//this alert below is for testing, everytime the like button is pressed it displays '#likesSize0' and i need it to spit #likesSize1,#likesSize2,#likesSize3 etc...
alert(likesDivCount);
$.post($form.attr("action"), $form.serialize(), function(response) {
// only updates the first item :( (#likesSize0)
$(likesDivCount).text(response);
});
event.preventDefault(); // Important! Prevents submitting the form.
});
</script>
Looks like you have multiple forms with the same ID: '#likesform'. This is because your forms are generated in a loop.
I suggest you to remove the ID, replace it with a css class (or something else) and rewrite the JS to search for elements inside the target form, e.g.:
var $form = $(this);
var likesDivCount = $form.find("input[name=likesDivCount]").val();
Once you have valid html it will be easier to troubleshoot
I am using jquery ajax to post a form to my node.js server. I am trying to prevent the page from refreshing ( since trying to develop a SPA) using preventDefault function, but surprisingly it is redirecting. And moreover, the data is being passed to the node express server very smoothly. But somehow it is skipping a couple of line it seems.
When I'm trying this in a basic POC, everything is working fine and it is preventing page refresh.
$(document).ready(function(){
$('#submit').click(function(event){
//$("form#foodForm").submit(function(event) {
window.alert( event.isDefaultPrevented() );
event.preventDefault();
window.alert( event.isDefaultPrevented() );
console.log("form submitted");
// Prevents the page from refreshing
var $this = $(this); // `this` refers to the current form element
$.post(
'/submittedData', // Gets the URL to sent the post to
$this.serialize(), // Serializes form data in standard format
function(data) {
console.log(data); /** code to handle response **/ },
"json" // The format the response should be in
);
});
});
app.js code:
app.post('/submittedData',function(req,res){
console.log('body: ' + JSON.stringify(req.body));
});
HTML piece:
<form id="foodForm" action="/submittedData" method="post">
<ul> Main course
<li> <input type="checkbox" name="items[]" value="roti">Roti </li>
<li><input type="checkbox" name="items[]" value="biryani">Biryani</li>
<li><input type="checkbox" name="items[]" value="rice">Rice</li>
</ul>
<ul> On the side
<li><input type="checkbox" name="items[]" value="chicken">Chicken</li>
<li><input type="checkbox" name="items[]" value="mutton">Mutton</li>
</ul>
<button id="submit">Submit</button>
<!-- <input type="submit" value="submit" id="submit" > -->
</form>
add
return false;
in the end of your function in js code..this will stop the normal page relaoding and form submission.
Try it and tell me
The problem is solved now. And the answer is well.. crazy. And I couldn't find out the root cause though.
I was writing the js code in a separate file and referencing it (properly), like we usually do. But although the post was happening the page was reloading.
I copied and pasted the js code in the html page itself inside script tags and boom!! it works..
You should use form.on("submit") event , in your case even if you successfully canceled the click button event if the user hit the enter button while typing in one of the input fields your Ajax code will not work
I have a popup modal that displays on page load that has the following form in it:
<form class="enterForm">
<label class="modalFields" id="userName" style="display: none;">
<span>user Number :</span>
<input type="text" name="userNum" placeholder="User Number" required/>
</label>
</form>
<label>
<span> </span>
<input type="submit" value="Submit" class="submitButton">
<input type="hidden" id="hiddenInput">
</label>
And on user submission of the form, I want to hit a certain API via an AJAX call, which returns a JSON that looks like:
{
"results":[
{
"person":{
"firstName":"John",
"lastName":"Smith"
},
"userNumber":"12345"
}
]
}
If the userNumber matches the value that the user submitted, I then want to update the nav bar to say the person's first name. In terms of process flow I want it to go: user types in user number -> submits form -> AJAX call hits API -> checks to see if user input matches userNumber value in JSON --> if match, selects the firstName value and updates it in the nav bar. How could I go about achieving this?
Considering you know how to do AJAX calls and you're using an API, integrating jQuery to facilitate the thing shouldn't be too hard (if it is, I included additional information after the solution).
Solution
JavaScript
//On form submit
$('#enterForm').submit(function(){
var userNum = $('[name="userNum"]').val();
//AJAX call to your API
$.ajax({
url: 'myAPICall.php',
/* data: {userNumber: userNum}, //If necessary */
success: function(data) {
// Note: this code is only executed when the AJAX call is successful.
if(data.results.userNumber == userNum){
$('#navBarFirstName').text(data.results.person.firstName);
}
},
error: function (err) {
//If the AJAX call fails, this will be executed.
console.error(err);
}
dataType: 'JSON'
});
return false; //Prevents the page refresh if an action is already set on the form.
});
Explanation
You use jQuery to bind a function (event listener) to the submit event of your form.
When the submit event is triggered, the function runs:
It gets the value of your DOMElement with the name attribute "userNum"
It makes an AJAX call to your API (with/without the userNum value, you choose if you want to check that on the server side or not)
On success, (when the call is done successfully), it updates the navbar content using .text() with the firstName attribute of your JSON response.
Including jQuery
You can integrate jQuery by including the script within your HTML page. You can either download it or use a CDN:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js">
/* Don't put your code in here it won't be parsed */
</script>
<!-- the following tag could also be <script src="link/to/your/script.js"></script> -->
<script>
/* Your actual script */
</script>
Make sure to put this line before your actual javascript file containing the script written above, otherwise jQuery won't be initialized and the script won't work.
UPDATED:
Okay, Thanks to OneSneakyMofo's Help below, I have managed to use ajax to call a submit.php form and have it return for example an echo statement. My problem is that none of my $post values are being carried over, for example if my start my php script with if (isset($_POST['pizzacrustformid'])) { the javascript will return blank, also when I do a var_dump($_POST);, Nothing is being saved into it which means the data is not being carried over, the php script is just being called. Please let me know if there is something I need to do in order to get the POST information to get carried over from the form as it would with a
< Submit > Button traditionally.
I Have Updated my code on Github to reflect my progress. https://github.com/dhierholzer/Basiconlineordering Thanks Again!
ORIGINAL POST:
I am new to using jquery and having forms be submitted without loading a newpage /refreshing the page.
In my Code I have multiple forms on one page that display one at a time via fade in and out effects by hitting the next button.
My problem is now that I do this, I cannot seem to get a PHP script to activate when hitting the next button to save those form options into sessions.
So here is an example:
<!--First Pizza Form, Pick Pizza Crust Type-->
<div id="pizzacrust">
<form method="post" name="pizzacrustform" id="pizzacrustformid">
<div id="main">
<div class="example">
<div>
<input id="freshpizza" type="radio" name="pizzacrust" value="1" checked="checked"><label style="color:black" for="freshpizza"><span><span></span></span>Fresh Dough</label>
</div>
<div>
<input id="originalpizza" type="radio" name="pizzacrust" value="2"><label style="color:black" for="originalpizza"><span><span></span></span>Original</label>
</div>
<div>
<input id="panpizza" type="radio" name="pizzacrust" value="3"><label style="color:black" for="panpizza"><span><span></span></span>Deep Dish Pan</label>
</div>
</div>
</div>
</form>
</div>
<div><button href="#" id="btn">Show Pizza Size</button></div>
So this Is my First Form, One thing to pay attention to is that instead of a < Submit > button, I am using a normal button and using javascript to do the submitting part.
Here is that Javascript:
<!--Controls All Button Fades-->
$('#btn').click(function(e){
$('#pizzacrust, #btn').fadeOut('slow', function(){
$('#pizzasize, #btn2').fadeIn('slow');
$('#pizzacrustformid').submit();
});
});
and Then:
$(document).ready(function () {
$('#pizzacrustformid').on('submit', function(e) {
e.preventDefault();
});
});
Now Traditionally being a php programmer, I just had a button in my form and then my php activated by having something like:
if (isset($_POST['submitted'])) { //MY Code To save values into sessions}
I cant seem To Get a function like that working when the form is submitted via a javascript function as I have it.
Here is my full code in my GitHub which may make it easier to see more so how these forms are working together right now.
https://github.com/dhierholzer/Basiconlineordering
Please Let me know any solutions that might be possible
Thanks again.
Edit:
OP, it looks like you are wanting to do AJAX, but you don't have anywhere to submit your AJAX to. Firstly, you will need to create a file that accepts the form.
Let's call it submit.php.
With that in place, you can start working on the AJAX call. To begin, you will need to separate your code from index.php.
Take this out of index.php and put it in submit.php:
if (isset($_POST['pizzacrustformid'])) {
// use a foreach loop to read and display array elements
echo '<p>hello!<p>';
}
In your Javascript, you will need to do something like the following:
$('#btn').click(function(e){
$.ajax({
method: "POST",
url: "some.php",
data: $('#pizzacrustformid').serializeArray()
})
.done(function(data) {
alert(data); //should be "Hello world"
$('#pizzacrust, #btn').fadeOut('slow', function(){
$('#pizzasize, #btn2').fadeIn('slow');
});
})
.fail(function() {
alert( "error" );
})
.always(function() {
alert( "complete" );
});
});
What is happening here is is on submit, your form data will pass over to the submit.php page, and it will generate the PHP code. That code will hit the done function (if it's successful), call an alert, then fade out to the next section.
That should get you on the right path. I would create another branch and strip out all of the forms and work on getting this done before continuing.
Also, I would set this all up in one single form and show the first section, do some validation, and then move on to the next section before finally submitting eveyrthing you need.
Hope this helps.
I recommend you do requests via ajax, here a tutorial and examples:
http://www.w3schools.com/jquery/jquery_ajax_get_post.asp
delete all jquery functions about submit
create a file called blu.php with the php code
add the jquery code in index.php
with this you only do once request at the end. I hope this helps you.
<?php echo 'tus datos son: ';
echo ' '.$_POST["data1"];
echo ' '.$_POST["data2"];
echo ' '.$_POST["data3"]; ?>
<script>
$(document).ready(function(){
$("#btn5").click(function(){
var pizzacrust= $('input[name="pizzacrust"]:checked').val();
var pizzasize= $('input[name="pizzasize"]:checked').val();
var pizzatoppings= $('input[name="pizzatoppings"]:checked').val();
$.post("blu.php",
{
data1: pizzacrust,
data2: pizzasize,
data3: pizzatoppings
},
function(data,status){
alert("Data: " + data);
});
});
});
</script>
I think you need to using click() func call ajax, dont use on() submit. Submit action makes current page will refresh. I will review your code later, but you should to try this solution above.