AJAX: Submitting form without page refresh only works once - javascript

I am using AJAX to submit a form behind the scenes, without refreshing the page. The problem I am running into is I can only submit the form once. After I submit it once, the on('submit') function no longer works and I am getting no errors. This completely defeats the purpose of using AJAX to submit the form :/
$(document).on('submit', '#myForm', function(e) {
$.post('mail.php', $(this).serialize(), function (data) {
//SUCCESS
$('.successORfail').html(data);
setTimeout(function(){
$(".successORfail").fadeOut("slow", function () {
$(".successORfail").remove();
});
}, 4500);
}).error(function() {
alert("Fatal Error: mail.php not found!");
});
e.preventDefault();
});
I was wondering if someone ran into a similar problem or knows how to solve this? I would like to be able to submit the form more than once, making changes to the form input values after each submit, if needed.
Many thanks in advance

Are you sure the AJAX request is not happening? It looks like you are removing the .successORfail element from the page, and thus the there is nothing to append the content to on subsequent calls.
Check your console and you will probably notice an ajax call happening each time.
Try changing your setTimeout to this:
var msgEl = $(".successORfail");
setTimeout(function() {
msgEl.fadeOut("slow", function () {
msgEl.empty().show();
});
}, 4500);

Your success event handler:
$('.successORfail').html(data);
setTimeout(function () {
$(".successORfail").fadeOut("slow", function () {
$(".successORfail").remove();
});
}, 4500);
is setting content in an element (.successORfail), then removing that element. The next time you submit the form, get a successful response, and that function is executed the element is no longer there to set the content into so you wouldn't see anything change.

Instead of removing the element, just .hide() it so that the next time it can be populated. You'll need to .show() it each time too.
$(document).on('submit', '#myForm', function(e) {
$.post('mail.php', $(this).serialize(), function (data) {
//SUCCESS
$('.successORfail').html(data).show(); //<-- show
setTimeout(function(){
$(".successORfail").fadeOut("slow", function () {
$(this).hide(); //<-- hide
});
}, 4500);
}).error(function() {
alert("Fatal Error: mail.php not found!");
});
e.preventDefault();
});
Also in the fadeOut() function, you can access the element with $(this) instead of re-selecting it based on the class name.

Can you add some HTML-snippet? Its hard to help without knowledge about your html-structure, because if you are replacing the form via $('.successORfail').html(data); the listener isn't re-bound to the form.
You should also return FALSE because the form-data is sent via javascript.

Well, it seems that you append your result to $('.successORfail').html(data); and the remove it. Take out the following and it should work multiple times...
$('.successORfail').remove();
Without that element, the change can't be made.

Related

Ajax sends request more than once

I have a huge problem with working with AJAX:
After the AJAX request on my page is send the next request are send multiple times, and buttons think that they are pressed multiple times.
Now I searched around here and the internet, but I can't solve it. So far, following corrections are made in the code:
All code is in an own function called AjaxInit()
AjaxInit() is called upon $(window).load and on $(document).ajaxStop
All Element have their binder to body (e.g. $("body").on("click","#btn-main", function)
Now I have tried unbinding all events using $("body").find("*").off(), but that did not help either.
I know that I do something wrong, I just don't know what.
How can I properly rebind everythink after the Ajax call is done? How can I make shure that object bindings (e.g. $("#news").sortable({})) will work properly after the first ajax call? I would love to use AJAX for all the callbacks on my page, but currently the best solution seems to be just reloading the entire page after every ajax call, which would be rather bad.
Any help is appreciated.
EDIT: Code added
$(window).load(function() {
AjaxInit();
});
$(document).ajaxStop(function() {
AjaxInit();
});
function AjaxInit() {
$("body").on("click", "#btn-admin-main", function(e) {
console.log("Admin clicked");
e.handled = true;
e.preventDefault();
LoadDynamicContent("/Edit/");
});
}
function LoadDynamicContent(path) {
//Nach oben Scrollen
$('html,body').scrollTop(0);
$.ajax({
type: 'GET',
url: path,
success: function(response) {
var html_response = $(response).find('#dynamic_content').html();
$("#dynamic_content").html(html_response);
}
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<a class="sidebutton-full" id="btn-main">Edit</a>
<div id="dynamic_content"></div>
You can unbind the click event from button
$(document).unbind('click').on("click", "#btn-main", function () {
//do stuff here
});
OR
$(document).off("click", "#btn-news").on("click", "#btn-news", function () {
});
If your form submission hitting twice then you need to change your code little bit
$("#form_news_sort").submit(function(e){
e.preventDefault()
// do stuffer here
.
.
.
.
return false;
})
if you are still facing error , please comment below
The problem is that when your ajaxStop handler calls AjaxInit(), it adds another click handler to the body.
In your example code, it looks like you don't need ajaxStop at all. All it will do is add another click handler, which is the problem. Or if your real code does some more complex initialization that needs to run whenever all Ajax requests are complete, you should factor out the click handler assignment from whatever else needs to happen.

jQuery trigger click not working from AJAX success

When I click submit on a form, it makes an AJAX call. If the return value is success I want to open a file upload browser to upload a file from the system. For this I am using the trigger click from jQuery on success message. But it is not working. Below is the code for the AJAX call.
$.ajax({
url: AppManager.defaults.contextPath,
data: colMap,
contentType: 'application/json',
type: 'POST',
success: function(data) {
if (data.result == 'Success') {
$('#continue-upload-input-box').trigger('click');
} else {
self.popupView.closePopup();
notify.popup('Error Uploading').error(self.uploadFailureMessage);
}
},
error: function(error) {
console.log(error);
}
});
This is where the code for file upload is written:
change: function($view) {
var self = this;
$('<form id="custom-upload" class="input-form-container" enctype="multipart/form-data"></form>').appendTo($view.find('.btn-wrap'));
$view.find('.input-form-container').after('<input name="excelFile" type="file" id="continue-upload-input-box" style="display:none;">');
$view.find('#continue-upload-input-box').off('change').on('change', function(event) {
if (event.target.files.length === 1) {
self.uploadCustomTemplate(new FormData($('#custom-upload')[0]));
self.popupView.closePopup();
}
});
}
What could be an issue in the above code?
you need to action a dom click event, not a jQuery click event.
try:-
$('#continue-upload-input-box').get(0).click();
use
$(document).trigger
insted of
$('#continue-upload-input-box').trigger('click');
if you use document then it will execute your trigger event . if your id is not in DOM when you trigger click it will not execute so you have to load DOM again
Use on method for calling event.refer following link:
http://api.jquery.com/on/
first make sure your 'data.result' value 'Success' is in correct format or which value it will return then use this
$("#continue-upload-input-box").trigger("click");
i think your code is proper but it's all depends on your other jquery code
.trigger is more or less like a click.
to trigger some action/event the element or object must be in DOM before your trigger the event.
So if you load the form from JS and then append it in DOM the your function that allow the uploader to show must be in .load function OR its better that you append it in DOM before the ajax fires.
http://api.jquery.com/trigger/
Use $('#continue-upload-input-box').click();. That should be sufficient.

Using jQuery .attr or .prop to set attribute value not working

I've created a button with an attribute named 'loaded' and initial value of 'no'. Upon clicking the button I'm running some ajax and at the very end of it I'm trying to set the 'loaded' attribute to 'yes' so that the ajax is not run again if the user clicks on the button more than once.
I have something like this: http://jsfiddle.net/PDW35/2/
Clicking the button does not change loaded to 'yes'.
However, if you do an alert right after the .attr call like this:
alert($(this).attr('loaded'));
The alert box does contain 'yes' which doesn't help because once the user clicks, the same code above puts up a 'no' alert box on the screen.
It all behaves the same way if I use .prop() instead of .attr(). Am I missing a point here or .prop() and .attr() just don't work with custom attributes?
EDIT:
Updated jsfiddle using ajax based on the comments below: http://jsfiddle.net/PDW35/5/
I am not exactly sure of the reason why the original code isn't working, but the $this seems to be the cause for some reason. Try the below and it seems to work. Fiddle is here.
I will try to update the answer with the reason as soon as I find it.
var loaded = $(".preview-button").attr('data-loaded');
if (loaded === "no") {
$.ajax({
success: function (result) {
$(".preview-button").attr('data-loaded', 'yes');
alert($(".preview-button").attr('data-loaded'));
}
});
} else {
alert("data loaded");
}
Refer this thread and this seems to be the reason why the $this doesnt seem to work from inside the AJAX call.
reading the question ..
so that the ajax is not ran again if the user clicks on the button more than once.
i think you need one(), it allows the event to run just once.. no need of changing the attributes and properties
example
$(".preview-button").one('click',function(){
//your ajax stuff
alert('clicked!!!!');
});
You can set property for your click (or submit) function:
$( ".preview-button" ).click( function() {
this.ajaxCompleted = this.ajaxCompleted || false;
if ( !this.ajaxCompleted ) {
// run your request and set this.ajaxCompleted to true in a callback;
}
// do other stuff
} );
you could try the following code: once you clicked data is loaded, second time click will alert that data is loaded already.
$(".preview-button").click(function(){
var id = $(this).attr('button_id');
var loaded = $(this).attr('loaded');
if(loaded == "no"){
$(this).attr('loaded', 'yes');
}else{
alert("Data is loaded");
}
});
working example here: http://jsfiddle.net/PDW35/4/
just change the click function with 'on' like this example:
$(document).on('click', '.element', function () {
let myelem_attr= $(this).attr('data-my-attr');
}

jquery function not getting called inside of an ajax function

So im trying do disable links on some <li> ellements that have been loaded in from another page using an .load() function, but for some reason i'm not able to effect those list items.
var from_post = false;
$(document).ready(function() {
//so this is the function that loads in data from another page
$("#gallery").load('http://localhost/index.php/site/gallerys_avalible/ #gallerys_avalible'), function() {
console.log('hello');
// sense there are no other li elliments on the page i thought this
// would be okay. but this function never gets called, i've moved it
// all over i just recently attached it to the load function thinking
// that maybe if the load was not complete it would not run, but i
// have had no luck.
$('li').click(function (e) {
e.preventDefault();
console.log("I have been clicked!");
return false;
});
};
$('#addNew').click(function () {
console.log('i got called');
$('#new_form').fadeIn(1000);
});
$('form').submit(function() {
if(from_post) {
//submit form
return true;
} else {
//dont submit form.
return false;
}
});
any help would be greatly appreciated, oh and the other thing is that i can run this function through firebug, and it works 100% fine. so im stumped.
You are closing your call to .load() too early. You have:
$("#gallery").load('http://...'), function() {
That just calls load and then declares a function. But, that function is not bound to the success handler and it will never be executed. You need the ) to be on the other side of the function declaration so that the function is included as a parameter to your call to load:
$("#gallery").load('http://...', function() {
...
});
Fix that and your code works: http://jsfiddle.net/gilly3/WdqDY/
Try a future-proof event observer like live or delegate:
$('li').live('click', function(){})
or, this method is preferred if you know the parent:
$('#gallery').delegate('li','click',function(){})
The reason for needing this is your click events are being bound to elements that are on the page at the time of the binding. Any li's added later will not see that binding which is how live or delegate works. They bind to the parent and traverse the child nodes every (click in this case) event to see if the event applies to an existing child.
Use .live('click', ...) or .delegate() instead of .click(...).

mvc dropdown change event firing only once?

I am submitting an AjaxForm with the help of javascript triggered by change event of this dropdownlist and update the div (that contains ddlist too) accordingly.
$(function() {
$('#Page').change(function() {
alert("testing");
var value = $(this).val();
if (value != "<%=Model.CurrentPage%>") {
$("#pageJump").click();
}
});
});
<div id = "updateDiv">
<%=Html.DropDownList("Page", Model.dropDown)%>
</div>
updateDiv is being updated by some Ajax stuff. DropDownList is correctly populating the items, but it fires the above javascript thing only once(after it has been posted once), not the second time. Why is it doing that?
EDIT:
$(function() {
initPaging();
});
function initPaging() {
alert("TEST");
initPagingDdl();
}
function initPagingDdl() {
$('#Page').change(function() {
alert("all");
var value = $(this).val();
alert(value);
if (value != "<%=Model.CurrentPage%>") {
$("#pageJump").click();
}
});
}
Inside my AjaxOptions constructor, I have set:
OnComplete = "initPaging"
It is still NOT working. It's calling the TEST after the Ajax post, so it's hitting the code, but not binding for some reason?
Whenever you update content of your updateDiv using AJAX, DOM refreshes each time. I'm not much sure, but it unbinds all events associated with its child. Hence your function is getting executed once only.
You can use either
Binding of click event in callback method of your ajax call OR
bind click event to
$('#updateDiv select').change(function() {
}); // not sure may work

Categories

Resources