Folks,
I'm learning Ajax by tinkering. At first, I had a form with button, which made an Ajax call to a dummy controller action. The HTML and JavaScript on the client side.1
<form method="post">
<button name="btnSaveProject" title="When you save this project, it willl be available for 30 days.">
Save
</button>
</form>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.1.min.js"></script>
<script>
$(document).ready(function () {
$("button[name='btnSaveProject']").click(function () {
console.log("make ajax call");
$.ajax({
url: "/Project/Save",
type: "GET",
timeout: 8000,
cache: false
}).done(function () {
console.log("ajax call successful");
}).fail(function (jqXHR, textStatus) {
console.log("something went awry. " + textStatus);
}).then(function () {
console.log("always just in case");
});
});
});
</script>
A strange thing was happening when I clicked the button. The Ajax call would reach the server (I know thins because I had a break point in the controller action, which triggered). But neither neither .done(), nor .fail(), nor .always() was getting called back on the client-side.
Then I have moved the <button> out of the <form>, and now .done(), and .always() get called back as expected. There seems to be some interplay between the can Ajax call. What is this interplay? Where can I learn more about it? What do I have to do to be able to use Ajax inside a <form>?
Here's the server-side code, but I suspect that it's a non-factor.
// AJAX: /Project/Save
public ActionResult Save() {
System.Threading.Thread.Sleep(600); /// <bring-up>A bit of latency to make the Ajax call more noticeable.</bring-up>
return Json("lorem ipsum", JsonRequestBehavior.AllowGet);
}
1 I have stripped down the code and kept only the parts that I think are applicable to the question. If I have stripped down too much, please let me know: I'll post more code.
You can add a type to your button:
<button type="button" name="btnSaveProject"
or just prevent the defaults of button to submit the form with event.preventDefault():
$("button[name='btnSaveProject']").click(function (e) {
e.preventDefault();
// other code as is
});
Since the button is in a form its default click action is to submit the form, So in your case as soon as the ajax request is sent the actual page is submitted which I think is reloading the page causing the callback handler to unload that is why those are not getting called
One solution is to prevent the default action of the click event by calling event.preventdefault()
$(document).ready(function () {
$("button[name='btnSaveProject']").click(function (e) {
//prevent the default action of the button click which is to submit the form
e.preventDefault()
console.log("make ajax call");
$.ajax({
url: "/Project/Save",
type: "GET",
timeout: 8000,
cache: false
}).done(function () {
console.log("ajax call successful");
}).fail(function (jqXHR, textStatus) {
console.log("something went awry. " + textStatus);
}).then(function () {
console.log("always just in case");
});
});
});
But since you are using a form, instead of a button click event it will be better to use a form submit event like
$(document).ready(function () {
$("form").submit(function (e) {
//prevent the default action of the button click which is to submit the form
e.preventDefault()
console.log("make ajax call");
//your ajax code
});
});
Another option is to set the type of the button to button so that the form submit will not be triggered like
<button type="button" name="btnSaveProject" title="When you save this project, it willl be available for 30 days.">Save</button>
Related
I have an MVC application and one of the views contains a button with a condition.
<i class="fa fa-sticky-note-o"></i>Did Not Eat
<button type="button" id="btnRemoveDidNotEat" class="btn btnRemoveDidNotEat">Remove Did Not Eat</button>
On click of btnRemoveDidNotEat,btnRemoveDidNotEat is hidden.
If btnDidNotEat is clicked,btnRemoveDidNotEat is shown.
Here is my JS code.
$('.btnDidNotEat').on('click', function () {
$.ajax({
}).done(function (partialViewResult) {
$('#btnRemoveDidNotEat').show();
});
});
$('#btnRemoveDidNotEat').on('click', function () {
$.ajax({
}).done(function (partialViewResult) {
$('#btnRemoveDidNotEat').hide();
});
});
The functionality works for the first time. On click of ".btnDidNotEat", the other button '#btnRemoveDidNotEat' is shown. On click of '#btnRemoveDidNotEat', it is hidden as required.
However the second time,On click of ".btnDidNotEat", the other button '#btnRemoveDidNotEat' is shown. But the button click function for '#btnRemoveDidNotEat' is not called.
I have tried doing the same with style="display:none;", but that gives me the same issue. I have also tried using toggle.
Am I missing something?
EDIT : Simplified the question to make it more clear.
I am not sure I understand your question right, but it looks like your AJAX response seems to have a partial view result. If you are trying to access the button click event of that partial view of AJAX, it will not hit the click event because it will not be attached to the DOM. So instead of your code, you should use something like this.
$("body").on("click", ".btnRemoveDidNotEat", function() {
$.ajax({
}).done(function (partialViewResult) {
$('#btnRemoveDidNotEat').hide();
});
}
I'm not sure if I understood your question correctly, but here is what I got fiddle
Here is some improvements of your script:
$('.btnDidNotEat').click(function () {
$.ajax({
}).done(function (partialViewResult) {
$('#btnRemoveDidNotEat').toggle();
});
});
$('#btnRemoveDidNotEat').click(function () {
$.ajax({
}).done(function (partialViewResult) {
$('#btnRemoveDidNotEat').toggle();
});
});
You can use toggle() function instead of adding and deleting class.
my following javascript function is sending the form multiple times.
4 to 9 posts at the same time and I cannot get it right now.
Here is the function:
function formModal(url, id, type, text, send_type) {
$(document).ready(function () {
$('#' + id).on('submit', function (e) { //id of form
$.ajax({
url: url, // PHP file
data: $(this).serialize(),
type: send_type,
success: function (data) {
console.log(data);
// Success Alert
swal({
html: true,
title: text,
type: type,
timer: 1500,
showConfirmButton: false
});
setTimeout(function () {
// Refresh after 2 seconds
window.location.href = "";
}, 2200);
},
error: function (data) {
//Error Alert
swal("Oops...", "Something went wrong :(", "error");
}
});
e.preventDefault(); //This is to Avoid Page Refresh and Fire the Event "Click"
});
});
};
The function will be used in a HTML/ PHP Script:
<script> formModal('/dashboard_scripts/module/wiki/edit_wiki_article.php', 'edit_article', 'success', 'Artikel wurde gespeichert', 'GET') </script>
what are you doing in your code , why $(document).ready() inside the function formModal() and then inside that $(document).ready() you are binding submit handler which means every time you call the formModal() you are binding a submit event handler and thats the main reason of multiple submits of the form. you should either remove the submit handler from the function and make a simple ajax call or change
$('#'+id).on('submit', function (e) {
to
$('#'+id).off('submit').on('submit', function (e) {
Sweet Alert has nothing to do with the multiple submits of your form
I'm using Twitter Bootstrap's button loading state (http://twitter.github.com/bootstrap/javascript.html#buttons).
HTML:
<input type="submit" class="btn" value="Register" id="accountRegister" data-loading-text="Loading..."/>
JS:
(function ($, undefined) {
$("#accountRegister").click(function () {
$(this).button('loading');
$.ajax({
type:"POST",
url:"/?/register/",
data:$("#loginForm").serialize(),
error:function (xhr, ajaxOptions, thrownError) {
$("#accountRegister").button('reset');
},
success:function (data) {
$("#accountRegister").button('reset');
}
});
return false;
})
})(jQuery);
But if I have many buttons I need to write many functions (?).
Of course I can make something like this:
$(".ajax-button").bind("click", function() {
$(this).button("loading");})
And I can use jQuery Ajax event ajaxComplete
$(".ajax-button").bind("ajaxComplete", function() {
$(this).button("reset");})
But this way ALL buttons will be set to normal state when any Ajax request completed.
If user will click on button1 and then click on button2 (both buttons are sending Ajax request), they will be set to normal state when first Ajax request is completed. How to determine which button I need to set to a normal state?
Thank you in advance.
UPDATE
All I need is determine which button triggered some action (Ajax request), set it state to loading and when Ajax request will be completed set it state to normal.
I found solution for my question =)
After reading jQuery documentation I wrote this code for my system:
core.js:
(function ($, undefined) {
$.ajaxSetup({
beforeSend:function (xhr, settings) {
if (settings.context != undefined && settings.context.hasClass('btn')) {
settings.context.button('loading');
}
},
complete:function () {
this.button('reset');
}
});
})(jQuery);
account.js:
(function ($, undefined) {
$("#accountRegister").click(function () {
$.ajax({
context:$(this), // You need to set context to 'this' element
//some code here
});
return false;
})
})(jQuery);
This works perfectly.
Hope that this will be useful for someone.
I can only modify the code in the ajax call.
The ajax call occurs when I click the submit in form named $('#form1').
$('#form1').submit(function () {
$.ajax({
url: 'some.php',
type: 'POST',
data: somedata,
success: function (msg) {
if (!msg) {
// I wanna to stop '#form1' submit here,how to do that? I can only modify the code in the ajax call.
}
}
});
});
You'll need to stop it BEFORE the success handler. Because the function finishes executing after your AJAX call the form will submit while your ajax call is occurring (and by the time your ajax call finishes it is too late).
But yes, put return false at the end of your function.
function SubmitHandler(){
// Your AJAX call here
// blah blah blah
return false; // Stop form submit
}
If it's really important that it is in the success handler, then you could execute the call synchronously.
You can also use preventDefault()
http://api.jquery.com/event.preventDefault/
return false or event.preventDefault should help you:
$('#form1').submit(function(){
$.ajax({
url:'some.php',
type:'POST',
data:somedata,
success:function(msg){
if(!msg){
//i wanna to stop form1 submit here,how to do that? you can only modify the code in the ajax call
}
}
});
return false;
});
or:
$('#form1').submit(function(e){
e.preventDefault();
$.ajax({
url:'some.php',
type:'POST',
data:somedata,
success:function(msg){
if(!msg){
//i wanna to stop form1 submit here,how to do that? you can only modify the code in the ajax call
}
}
});
});
Put a
return false;
This should stop the function to continue
You need to prevent form submitting
onclick="ajaxcall(); return false;"
And do it in your code:
$.ajax({
url:'some.php',
type:'POST',
data:somedata,
success:function(msg){if(msg) $('#form1').submit();}
})
You can change button type from "submit" to "button" then submit form using jquery form.submit(); function according to your conditions. Consider the following example code below:
<script>
$(document).ready(function() {
$("#button-id").click(function() //on click at button
{
var sel=$("#input").val();
$.post("ajax-war.php",{jid:sel,rand:Math.random() } ,function(data)
{
if(data=='valid') //if correct login detail
{
$('#war_form').submit(); //Submit form
}
else
{
alert('not valid'); //will not submit form
}
});
});
});
</script>
Assuming the form's ID is #form1, you could bind a submit handler and return false from it:
$.ajax({
url:'some.php',
type:'POST',
data:somedata,
success:function(msg){
if(!msg){
$('#form1').submit(function(){
return false; // prevents form submit
});
}
}
})
I am trying to allow a button to be clicked only once and then some data be submitted via ajax. The problem I am facing is that a user can click 50x and the data is POST submitted each time ?
jQuery("#id").unbind('click');
jQuery.ajax({
type: "POST",
url: ajax_url,
data: ajax_data,
cache: false,
success: function (html) {
location.reload(true);
}
});
How can I ensure that if a user clicks #ID 100x - that the data is only submitted once ? And then #ID is re-enabled ?
You could use the .one() function in jQuery.
jQuery("#id").one('click', function()
{
jQuery.ajax({
type: "POST",
url: ajax_url,
data: ajax_data,
cache: false,
success: function (html) {
location.reload(true);
}
});
});
Bear in mind this will completely remove the click event, even if you have an error with your ajax, you still won't able to click it again.
just disable the button
$("#id").attr("disabled", "disabled")
and then in the success function enable it
$("#id").removeAttr("disabled")
Easiest way would be to use a flag which gets reset when the success is fired:
if(clicked == False){
clicked = True;
jQuery("#id").unbind('click');
jQuery.ajax({
type: "POST",
url: ajax_url,
data: ajax_data,
cache: false,
success: function (html) {
location.reload(true);
clicked = False;
},
error: function () {
alert("Error happened");
clicked = False;
}
});
}
You can disable to control, or use one of the many modal libraries to show the spinning wheel
see this Jquery modal dialog question on SO
You could disable the button on click event and enable it back when ajax request is completed.
In your click event you could disable the button and then re-enable the button in the success function of the ajax event.
Another option would be to set a parameter on the element that is being clicked to indicate the button was clicked and then check to see if it is set if it is don't send the ajax request if not then do send it. Once the ajax is done you can unset the parameter again to allow it to be run.
try this:
$(document).ajaxStart({ function() {
$('#submit_button').click(function(){
return false;
});
});
where: #submit_button is id of the element U want to disable
that code will disable clicking on the submit button