I created a form on /contact-us and having action="/contact-us". Now, when I added Ajax to it, it is sending the request three times, i cannot find the reason.
Ajax:
define(['jquery', 'foundation.alert'], function($) {
return {
init: function() {
$("#success-alert").hide();
$("#error-alert").hide();
$('button').click(function(e){
$('input').map(function() {
if(!$(this).val()) {
$("#error-alert").show();
$("#success-alert").hide();
return false;
} else {
$('document').ready(function() {
var form = $('#contact_us'); // contact form
var submit = $('button'); // submit button
var status = $('#form-status'); // alert div for show alert message
// form submit event
form.on('submit', function(e) {
e.preventDefault(); // prevent default form submit
$.ajax({
url: '/contact-us', // form action url
type: 'POST', // form submit method get/post
dataType: 'html', // request type html/json/xml
data: form.serialize(), // serialize form data
beforeSend: function() {
submit.html('Sending....'); // change submit button text
},
success: function(data) {
form.trigger('reset'); // reset form
$("#success-alert").show();
$("#error-alert").hide();
submit.html('Send'); // reset submit button text
},
error: function(e) {
console.log(e);
}
});
});
});
}
});
});
}
}
});
You are looping through all the inputs and applying on submit for every input in your form. So if it is submitting 3 times, you must have three inputs. Each time you click the button, you will be adding even more submit handlers! The whole design of this is wrong.
You should not be attaching the submit handler inside of the click event, it should be outside and have it done one time. Do your validation inside of the submit handler to make sure that it is valid before making the Ajax call.
try this solution.
var wait = false;
wait variable for global scope
if (!wait) {
wait = true;
$.ajax({
url: '/contact-us', // form action url
type: 'POST', // form submit method get/post
dataType: 'html', // request type html/json/xml
data: form.serialize(), // serialize form data
beforeSend: function () {
submit.html('Sending....'); // change submit button text
},
success: function (data) {
wait = false;
form.trigger('reset'); // reset form
$("#success-alert").show();
$("#error-alert").hide();
submit.html('Send'); // reset submit button text
},
error: function (e) {
console.log(e)
}
});
}
After going through my code i realized what mistakes i have been doing and also realized that reading code is more important than writing it.
This is how i rewrite the code and its working fine but i am still not sure if it is the best approach.
define(['jquery', 'foundation.alert'], function($) {
return {
init: function() {
$("#success-alert").hide();
$("#error-alert").hide();
$(function () {
$('#contact_us').on('submit', function (e) {
$.ajax({
type: 'post',
url: '/contact-us',
data: $('#contact_us').serialize(),
success: function () {
$("#success-alert").show();
$("#error-alert").hide();
}
});
e.preventDefault();
});
});
$('button').click(function(e){
$('input').map(function() {
if(!$(this).val()) {
$("#error-alert").show();
$("#success-alert").hide();
return false;
}
});
});
}
}
});
Note: Never take writing code as a burden.
Related
It's probably sthg simple, but I still didn't find a solution, I would like to avoid multiple clicks on a button, before finishing an ajax call.
Here is what I tried :
<button id="btn_pay"></button>
$("#btn_pay").click( function() {
$('#btn_pay').prop('disabled', true);
Stripe.card.createToken(form, stripeResponseHandler);
});
var stripeResponseHandler = function(status, response) {
$.ajax({
type: "POST",
success: function(data){
alert("success");
},complete:function(){
//we re-enable the button
$('#btn_pay').prop('disabled', false);
}
});
Problem :
If I click several times on the button, many alerts appear, it's like the button is still active, and many ajax call are done instead of jsut 1 at a time..
Any idea ?
You can control it with a simple variable:
<button id="btn_pay"></button>
var disabled = false; // global var to control button state
$("#btn_pay").click( function() {
if (disabled) {
return;
}
Stripe.card.createToken(form, stripeResponseHandler);
disabled = true; // button is now blocked
});
var stripeResponseHandler = function(status, response) {
$.ajax({
type: "POST",
success: function(data){
disabled = false; // release button lock
alert("success");
},complete:function(){
disabled = false; // release button lock
},fail: function(){
disabled = false; // when fail, you need to release the lock too
}
});
}
Other solutions with event handlers may work for you too, but this is a simpler way to implement this feature.
Try e.preventdefault();
The event.preventDefault() method stops the default action of an
element from happening. For example: Prevent a submit button from
submitting a form. Prevent a link from following the URL.
I have Also facine this type of problem , i have prevent it by using this .. May be it will help you
<button id="btn_pay"></button>
$("#btn_pay").click( function(e) {
e.preventdefault();
$('#btn_pay').prop('disabled', true);
Stripe.card.createToken(form, stripeResponseHandler);
});
var stripeResponseHandler = function(status, response) {
$.ajax({
type: "POST",
success: function(data){
alert("success");
},complete:function(){
//we re-enable the button
$('#btn_pay').prop('disabled', false);
}
});
Modify your code:
.unbind() Remove a previously-attached event handler from the elements.
.bind Attach a handler to an event for the elements.
<button id="btn_pay"></button>
<script>
$("#btn_pay").click( function(e) {
$("#btn_pay").unbind("click");
$('#btn_pay').prop('disabled', true);
Stripe.card.createToken(form, stripeResponseHandler);
});
var stripeResponseHandler = function(status, response) {
$.ajax({
type: "POST",
success: function(data){
alert("success");
},complete:function(){
//we re-enable the button
$("#btn_pay").bind("click");
}
});
</script>
Checkout the tutorials :
http://api.jquery.com/bind/
http://api.jquery.com/unbind/
You can also avoid multiple clicks on button by adding loading image untill your ajax call is completed in beforeSend: event.
for example:
$.ajax
({
url: 'your-url',
data: "",
type: 'post',
beforeSend: function() {
$("#loading-image").show();
},
success: function(result)
{
//alert(result);
$("#loading-image").hide();
}
});
You have to keep image in div id 'loading-image' and by default display:none(CSS Setup).
<div id="loader_div_all" style="position: absolute ! important;opacity: 0.60;display: none;">
<img src="ajaxSpinner.gif" style="width: 200px; height: 200px; margin-left: 500px; margin-top: 1060px;'">
$("#buttonid").click(function(){
$.ajax({
url: 'PATH_TO_AJAX_REQUEST_URL',
type: 'POST',
data: {/*Data set here*/},
beforeSend: function () {
$("#loader_div_all").css('display','block');
},
success: function(resp) {
$("#loader_div_all").css('display','none');
/*Perform Ajax Success Action Here*/
}
});
});
Link the disabled state of the button to the response function firing. This way the visual cue and the button behaviour should match.
$("#btn_pay").click( function(event) {
event.preventDefault();
if ($(this).prop('disabled')) {
return;
}
$(this).prop('disabled', true);
Stripe.card.createToken(form, stripeResponseHandler);
});
(It would be better to pass a callback re-enabling the button to stripeResponseHandler, so that that function is not tied to a specific button calling it).
I have a page that uses ajax to render partial views for two forms (student, teacher). When I switch between the two forms (with nav links) and they are fetched and rendered with Ajax I loose my validation. So I tried adding some "reparsing" method to my code that gets called after I fetch the partial view. (links to SO threads SO link So link) This I think works because if I try and submit I see my validation errors showing, but now my Jquery submit events don't fire.
I have 3 events that submit the 2 different forms. Note - I'm loading the student partial view first so I need to have 2 events to catch this submission shown below.
$("#studentSubmit").submit(function(event) {
event.preventDefault();
submitStudentForm();
});
$(document).on('submit', '#studentSubmit', function(event) {
event.preventDefault();
submitStudentForm();
});
$(document).on('submit', '#teacherSubmit', function(event) {
event.preventDefault();
submitTeacherForm();
});
Here are the two calls to fetch the partial views and the method that reparses the form. When I add reparseForm() my 'studentSubmit' and 'teacherSubmit' submit events stop working.
$('#studentProfileLink').on('click', function(event) {
//load student profile
var options = {
url: '/Profile/LoadStudentProfile',
type: "post",
data: {}
};
$.ajax(options).done(function(data) {
$("#profileSection").html(data);
reparseform();
}).fail(function(jqXHR, textStatus) {
$('#errorHomePage').show().fadeOut(8000).text('Error Calling Server -' + textStatus);
});
});
$('#teacherProfileLink').on('click', function() {
//load teacher profile
var options = {
url: '/Profile/LoadTeacherProfile',
type: "post",
data: {}
};
$.ajax(options).done(function(data) {
$("#profileSection").html(data);
//reparseTeacherForm();
reparseform();
}).fail(function(jqXHR, textStatus) {
$('#errorHomePage').show().fadeOut(8000).text('Error Calling Server -' + textStatus);
});
});
var reparseform = function() {
$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");
};
It looks like by putting some of the submit events inside my ajax call, they now fire when I hit submit.
Here is what I did. I moved them from the $(document).ready(function () {}
to inside the ajax return call like this. Can anyone explain why they won't work if they are in $(document).ready?
$('#teacherProfileLink').on('click', function() {
//load teacher profile
var options = {
url: '/Profile/LoadTeacherProfile',
type: "post",
data: {}
};
$.ajax(options).done(function(data) {
$("#profileSection").html(data);
reparseform();
$("#teacherSubmit").submit(function(event) {
event.preventDefault();
submitTeacherForm();
});
$(document).on('submit', '#teacherSubmit', function(event) {
event.preventDefault();
submitTeacherForm();
});
}).fail(function(jqXHR, textStatus) {
$('#errorHomePage').show().fadeOut(8000).text('Error Calling Server -' + textStatus);
});
Background:
I want to submit my HTML form asynchronously using jQuery, except if the ajax call fails. If the ajax call fails, I want to re-submit my HTML form normally.
I cannot get the "submit normally on fail" to work. What happens is if the submit button is pressed again after a fail, it submits normally, but I want the form to be resubmitted automatically on fail.
I am using namespaces because I need the generic .on('submit', ...) to always populate the hidden field.
Question:
How do I need to redesign my code so that I can achieve the functionality I desire?
Code:
$('#form).on('submit', function(event){
$(this).find('#hidden_field').val('value');
});
$('#form').on('submit.as_ajax', function(event){
event.preventDefault();
var $this = $(this);
var post = $.post({
data: $this.serialize(),
url: $this.attr('action')
});
post.done(function(response, status, xhr){
$('#container').html(response);
});
post.fail(function(xhr, status, error){
$this.off('submit.as_ajax').submit();
});
});
I think this will work for you
function submitFormNormally($this) {
$this.submit();
}
function submitFormAsAjax($this) {
var post = $.post({
data: $this.serialize(),
url: $this.attr('action')
});
post.done(function(response, status, xhr){
$('#container').html(response);
});
post.fail(function(xhr, status, error){
submitFormNormally($this);
});
}
$('#submit-button').on('click', function(event){
event.preventDefault();
var $this = $('#form');
submitFormAsAjax($this);
});
Now, what you have to do is bind the submit button like this.
I was working on a simple form page and I was wondering what happens if someone clicks the submit button many many times (incase my shared hosting somehow seems to be slow at that time).
Also, incase anyone wants to look at my code
$.ajax({
url: "submit.php",
type: 'POST',
data: form,
success: function (msg) {
$(".ressult").html("Thank You!");
},
error: function () {
$(".result").html("Error");
}
});
Is there a way to make it so after the user clicks it once, it won't run it again until the first click is done?
Thank you
You can use jQuery's .one() function:
(function handleSubmit() {
$('#submitBtn').one('click', function() {
var $result = $('.result');
$.ajax({
url: 'submit.php',
type: 'POST',
data: form,
success: function (msg) {
$result.html('Thank You!');
handleSubmit(); // re-bind once.
},
error: function () {
$result.html('Error');
}
}); // End ajax()
}); // End one(click)
}()); // End self-invoked handleSubmit()
*Edit: * Added recursion for multiple submissions.
Use a boolean flag
if (window.isRunning) return;
window.isRunning = true;
$.ajax({
url:"submit.php",
type: 'POST',
data: form,
success: function (msg){
$(".ressult").html("Thank You!");
},
error: function (){
$(".result").html("Error");
},
complete : function () {
window.isRunning = false;
}
});
var $button = $(this);
$button.prop('disabled', true); // disable the button
$.ajax({
url:"submit.php",
type: 'POST',
data: form,
success: function (msg){
$(".ressult").html("Thank You!");
},
error: function (){
$(".result").html("Error");
},
complete: function() {
$button.prop('disabled', false); // enable it again
}
});
Have you considered replacing your submit button with a loader image while the query executes, then re-adding it once the query is complete?
EDIT: Using the loader image is a sort of universal "I'm doing something" indicator, but disabling the button would work too!
You could disable the submit button, before the ajax call is made. And then, if required, enable it on success.
Doing following in jQuery:
$('#signupbox1').on('click', '#signup1', function() {
var str = $('#signupform').serialize();
// make it look like a waiting button
$('#signup1').addClass("btn_wait");
var btn_val = $('#signup1').val();
$('#signup1').val('');
$.ajax({
type: "POST",
url: "signup_step1.php",
data: str,
success: function(msg) {
//doing stuff here
$('#signup1').removeClass("btn_wait");
$('#signup1').val(btn_val);
}
});
});
How could you disable the click event as well till you receive an answer from the ajax call? So, when you click on the button it not only "transforms" to a waiting button because of the added class, but also the click event will be "paused"... is this possible?
Thank you very much in advance!
$('#signupbox1').on('click', '#signup1', function() {
var str = $('#signupform').serialize();
// make it look like a waiting button
var btn_val = $('#signup1').val();
$('#signup1').addClass("btn_wait").val('').unbind('click');
$.ajax({
type: "POST",
url: "signup_step1.php",
data: str,
success: function(msg) {
$('#signup1').removeClass("btn_wait").val(btn_val);
},
complete: function() {
$('#signup1').bind('click'); // will fire either on success or error
}
});
});
You can add a flag to denote "currently loading". You can use anything like a variable, property or attribute. In this example, I use jQuery .data()
Also, it's advisable that you use submit event instead of adding a click handler to the submit button when you submit a form.
$('#signupform').on('submit', function() {
var form = $(this),
loading = form.data('loading'), //check loading status
str, button, val;
//if not loading
if(!loading){
//set loading to true
form.data('loading',true);
str = form.serialize();
button = $('#signup1', form);
val = button.val();
// make it look like a waiting button
button
.addClass("btn_wait");
.val('');
$.ajax({
type: "POST",
url: "signup_step1.php",
data: str,
success: function(msg) {
//remove loading state
form.data('loading',false);
//return button to normal
button
.removeClass("btn_wait");
.val(val);
}
});
}
});