Ajax form submission on a form created using jquery - javascript

i am using a table with different rows and an edit button on each row.
This edit button creates a form using ajax / json to fill the form details depending on the row clicked.
The problem then comes when creating the ajax for this form.
Im using the same method as always, but for some reason the ajax submission is not working on this form and its just going to the process PHP page.
Im just wondering if this is because the form is not on the page when the javascript code for the ajax call is loaded?
So an example:
1) The page is loaded and included on that page is:
<script type="text/javascript" src="admin/js/showUserDetailsForm.js"></script>
<script type="text/javascript" src="admin/js/saveUserDetails.js"></script>
2) I click edit, and the showUserDetailsForm.js creates the form. The form is this:
$('<div id="admin-edituser-popup">'+
'<div id="login-popup-title">Edit User:<button id="closeedituserform">Close</button></div>'+
'<div id="login-popup-centre">'+
'<form class="editUserDetails-form" action="admin/process/saveUserDetails.php" method="POST">'+
'Editing Details for User:'+response.username+' , User ID:'+response.userID+
'<input type="hidden" name="userid" value="'+response.userID+'">'+
'<input type="text" name="username" value="'+response.username+'">'+
'<input type="submit" value="Save User">'+
'</form>'+
'</div>'+
'</div>').appendTo('body');
3) I click the submit button, and its correctly returns the JSON i am looking for (updateSuccess).
4) The form is not processed via ajax, its simply going to where its action is.
The code for the ajax call on save details is:
// JavaScript - Save user details
$(document).ready(function(){
// When the form is submitted
$(".editUserDetails-form").submit(function(){
$.ajax({
type: "POST",
url: "admin/process/saveUserDetails.php",
data: $(".editUserDetails-form").serialize(),
dataType: "json",
success: function(response){
if (response.updateSuccess) {
alert('Saved');
}
}
});
return false;
});
});
I cannot see any reasons why that its not working (cant find any errors with class names etc) and there is not errors in the javascript.
The only thing i am unsure of is the fact that the form is created AFTER the code is loaded?
Thanks!

For newly created DOM element handlers, you should use JQuery's on().
For your issue, you should just replace $(".editUserDetails-form").submit(function(){ with $("body").on('submit', '.editUserDetails-form', function(){
Last but not least, #Brunis is right - you should add event.preventDefault() to your method (event parameter is automagically injected)

If you want to intervene the default behaviour you should either
1. use e.preventDefault() in your onsubmit event callbackFunction or
2. use a "script" button that doesn't submit, eg. button type=button will not submit, but then you'll have to adjust your onsubmit event to just be an onclick event for that button.
Also, there's no need to have method and action in your form element when you don't want that to happen.

Related

Button created inside ajax call behaves differently than in standard html

I'm trying to create a table, populated by an ajax query where each row has a delete button next to it, so it can be easily removed.
However if I try to build the button inside an ajax query it doesn't seem to post correctly.
To ensure it wasn't the code inside the jquery click I created this simple function
$('.delbutt').on("click", function(event) {
var confirm = window.alert("good button pressing skills!");
return false;
});
The ajax query and div table filling is handled by this:
(function ajaxMapCalls() {
$.ajax({
url: mapgrabber,
dataType: 'json',
success: function(data, textStatus, xhr) {
$("#vcmaps").empty();
var output1 = "<table><tr><th>Customer</th><th>vCenter</th><th>Cluster</th><th>vSwitch</th><th></th></tr>"
$(data).each(function(i, el) {
var output2 = "<tr><td>" + el.customer + "</td><td>" + el.vcenter + "</td><td>" + el.cluster + "</td><td>" + el.vswitch + "</td><td><button class='delbutt'>delete</button></td></tr>";
output1 += output2;
});
$("#vcmaps").append(output1 + "</table>");
}
});
setTimeout(ajaxMapCalls, 2000)
})();
The table buttons are there it all builds fine but the button doesn't behave as expected, there's not a simple jquery popup and it seems to attempt to post server-side which it shouldn't be doing at this point.
So I tried putting a copy of the buttin inside the html.
Html of the relevant section below
<form action="#" method="POST" id="custVCassign"><div id="vcMenu"
class="flip"><h3>Assignment</h3></div>
<div class="panel">
Customer: <select class="select" id="custbag"></select><br>
vCenter: <select class="select" id="vCenter"></select><br>
Cluster: <select class="select" id="vCluster"></select><br>
Distributed switch: <select class="select" id="vSwitch"></select><br>
<button id="custvcdel" class="button2">Delete Cluster and Switch</button>
<button id="custvc" class="button">Add Cluster and Switch</button><br>
<button class='delbutt'>delete</button></form>
<div id="vcmaps"></div>
</div></form>
The button INSIDE the html works absolutely fine, it does the alert, but any buttons generated by the ajax into the div "vcmaps" don't behave correctly.
I wondered if it was because it was a div futher down and it was changing to a traditional post action so I wrapped the div in another form..
<form action="#" method="POST" id="custVCen"><div id="vcmaps"></div></form>
Still the same.
Any ideas what's going on here?
Your "click" event handler won't catch buttons that are created dynamically by the ajax call. They don't exist yet when the event handler is called, so it ignores them. And since you didn't specify a type="button" attribute for your dynamic buttons, they default to type="submit", which, if the button is inside a form, will cause your form to be submitted using a full postback when they're clicked (and there's no click handler to override this).
Use delegated event handling to get round this. You set the event on an element which will definitely exist when the event handler is called, and then tell it to delegate the events down to any elements which match the secondary selector at the time when the event fires. I don't know what element would be the lowest common ancestor of your buttons, so I've just used document as an example:
$(document).on("click", '.delbutt', function(event) {
See the "Direct and Delegated events" section here: http://api.jquery.com/on/ for more details.
Secondly, use preventDefault() to ensure there's no secondary postback triggered by the button. Put:
event.preventDefault();
as the first line of your "click" handler. See https://api.jquery.com/event.preventdefault/ for more info. This is more reliable than putting return false; at the end of your function, because it means there's no potential time gap between the event firing and the prevention of the default.

How to set Autoclick on all the buttons of a page?

I am using Jquery and Ajax for performing the action, I need after loading complete page, a code click on the every button automatically.
I used the following javascript code for click all the buttons in the end of my page. but it is not working.
<script type='text/javascript'>
document.getElementByClassName('sub').click();
</script>
Structure of my Page code
[JQuery]
[PHP]
[HTML]
[Javascript]
I set all the buttons type as "BUTTON", When I set
type="submit"
The Autoclick code only work on the first button, but with the "button" type it is not working with any of them.
If I click manually on that buttons they are working properly.
Please give any suggestion. Thank You.
Youre using the wrong function. Elements is plural in that method.
document.getElementsByClassName('sub');
Additionally, calling click on this NodeList will not work. You need to loop through and call the event on each index.
Also, you say you're using jQuery. To ensure your call happens after DOM ready, wrap your JS with $().ready().
Last, use the tools you've provided yourself, in this case jQuery, and select your element that way.
$(document).ready(function(){
$(".sub").click()
});
In jQuery you can trigger the click like
$( ".sub" ).trigger( "click" );
Because you retrieve a NodeList(as pointed out in the comments) :
$(document).ready(function () {
var butEl = document.getElementsByClassName('sub'),
count = butEl.length;
for (i = 0; i < count; i++){
butEl[i].click();
}
});
Also is getElementsByClassName
If you're trying to click on multiple different form submit buttons, it makes sense that the browser will POST for only one of them - one page can't simultaneously navigate to multiple different URLs.
Similarly, when you change type to button, none of the forms will be submitted, even though you're clicking on the buttons.
If you know what you're doing, you could always add submit event handlers to all of your forms, and submit them via ajax requests instead - which should allow multiple of them to be processed. Note you may need to work out some extra logic for displaying success/failure for each form to the user since the browser won't navigate you to any of the existing "submitted" pages.
$(document).on('submit', 'form', function() {
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
dataType: 'json',
data: $(this).serialize(),
success: function(data) {
// Add logic here for handling success for each form, if required
},
error: function(xhr, err) {
// Add logic here for handling errors for each form, if required
}
});
return false; // To stop the browser processing this form
});
With this method, your first attempt with type="submit" buttons should work - however I would encourage you to be as specific as possible with your element selectors for both the forms and the buttons you're trying to target.

Unable to submit a form on the first click event

Well, I spent hours on this problem and scanned the whole stackoverflow, but still do not know what to do. But what really gets me nuts is that such a trivial and the simplest in the world thing is not working. So, what I have now is a form with inputs and a button:
<form id="frm" action="/accent/login/enter/">
{% csrf_token %}
<div draggable="true" id="panel" class="panel" title="">
<input id="login" name="login" type="text" placeholder="" class="required" /> <br/>
<input id="pswd" name="pswd" type="password" placeholder="" class="required" /> <br/>
<button id="btn" value="">ENTER</button>
</div>
</form>
And I have this code which is supposed to send the form:
$('#btn').one("click",function(){ // prevent from multiple submits
$('#frm').validate({ // validate the form before submission
...general stuff: rules, messages, etc
submitHandler:function(form){
$('#frm').submit(function(e){ //submitted on the second click. why???
...prepare parameters for ajax call
$.ajax({
type:'POST',
...general stuff
});
e.preventDefault();
})
}
});
});
The problem is, when a user clicks on submit button for the first time, then the form is not submitted, if, however, he or she clicks it for the second time, then it is submitted ok. I can't understand the logic behind such behaviour implemented in jquery. Besides, I should say, that I have tried many other tricks, like:
form.submit(...
$('#frm')[0].submit(...
But they work not as expected, as if there is no callback function - I'm redirected to the url, but do not stay on the same page - just what I expect from e.preventDefault. I guess there is some sacred method or magic properties in jquery that I should use to make it work (like method one which prevents terrible multiple submits). But at this moment I do not know them.
EDIT
I also tried this trick:
jQuery('#frm').submit(...
but it works exactly like the first method - $('#frm').submit(...
EDIT
I found the third method which works like the previous one:
$('form').submit(...
To sum up, I have three different methods, but all of them work only when a user clicks on the button for the second time. And I have two methods that work in a standard manner and do not make it possible to use a callback function.
The problem is, you are registering for form submit after the form validation.
so,
1) On first click of button validation, the submit event is registered to a handler.
2) On second click of the button, the registered handler will be called. that is why it get submitted on second click. But note that you are registering again for the submit event. which means, on third click the form will be submitted twice, on fourth click the form will be submitted thrice..... and so on...
Solution
1) remove the $("#frm").submit() code from the submitHandler and put it outside.
2) use e.preventDefault(); in $("#frm").submit() so the default action is prevented and page doesn't get reloaded.
3) put the AJAX code directly in submitHandler
$('#btn').one("click",function(){ // prevent from multiple submits
$('#frm').validate({ // validate the form before submission
...general stuff: rules, messages, etc
submitHandler:function(form){
...prepare parameters for ajax call
$.ajax({
type:'POST',
...general stuff
});
}
});
});
$('#frm').submit(function (e) {
e.preventDefault();
});
I guess you are using the jqueryvalidation plugin. If it's true, then your using of $().validate() may be wrong.
The $().validate() function is to initialize the validation, it tells the script how to validate the form value and what to do if the validation is passed(the submitHandler property).
So maybe you should edit your code like this:
<form id='frm'>
...
</form>
$('#frm').validate({
//...general stuff: rules, messages, etc
submitHandler: function (form) {
//blahblah before doing the submitting...
form.submit();
}
});
$('#btn').one('click', function (){
$('#frm').submit();
});
But, actually there's still a problem with your $btn.one() event handler: if you click the button while the form values doesn't meet your validation rules, the one chance to fire the handler is consumed and even if you re-input the right value, the button will never response your clicking unless refreshing the page.
So maybe you should check your business logic again and redesign the form submitting flow, but that's not what this question is discussing, good luck ;)

Hiding And Submitting A Form Using jquery

How to Hide a form and submit that form using jquery?
Is this possible?
Yes, it is possible:
On your HTML page:
<form id="my-form">
</form>
Submit
Your script:
$(document).ready(function() {
$("a#submit").click(function() {
$("#my-form").hide();
$("#my-form").submit();
});
});
If your form contains a Submit button and you want the form to be hidden when the Submit button is pressed, instead you can listen to the submit event and handle it like this:
$("#my-form").submit(function() {
$(this).hide();
return true;
});
What are you trying to do? Some scam?
You can place the form in a hidden div and using $(document).ready event, you can autosubmit the form.
Do you mean a field within a form that already has data inserted, eg. hard-coded in by you, the developer?
If this is the case, just set an id to the input field, with the value hard-coded in. Then set it's display to 'none'. Use your Jquery to interpret the data as normal.
You could also just make a variable in your jquery script, and avoid all this.
Since you've added the jquery-ajax tag, I guess you want to submit the form through AJAX. In that case you are probably looking for something like this:
$("#your-form-id").submit(function(){
$.ajax({
type: "POST",
url: "some.php",
data: $(this).serialize(),
success: function(){
$("#your-form-id").hide();
}
});
return false;
});

Hidden iFrame file upload submits an extra time on each subsequent submit

I'm trying to create a simple file upload form for my website. I'm using a hidden iFrame to do it "ajax" style so I can have a user upload files one after another using the same form.
Right now I have a form with an <input type="file" />. What I have happening is when the input field changes(user selects a file) it should submit the form with the target set to the iFrame which loads a php script and then reset the input field to allow the user to upload again. What seems to happen is the form gets submitted based on the amount of times the form was submitted. e.g if you press the button when the page loads it will submit one time, however if you press the button again(without reloading the page) it will submit two times, and when you press the button for a third time it will submit the form three times and so on.
Here is my javascript for when the input changes
newupload is the id of the input
newimgform is the id of the form
postframe is the id of the iframe
$("#newupload").change(function() {
var max = 5242880, iframe = $("#postframe"), iframeContents;
$('#newimgform').attr("action", "uploadPicture.php")
$('#newimgform').attr("method", "post")
$('#newimgform').attr("MAX_FILE_SIZE", max)
$('#newimgform').attr("enctype", "multipart/form-data")
$('#newimgform').attr("encoding", "multipart/form-data")
$('#newimgform').attr("target", "postframe")
$('#newimgform').submit();
$("#postframe").load(function() {
iframeContents = jQuery.parseJSON($(this.contentDocument).find('body').html());
alert(iframeContents.filename);
$("#newimgform")[0].reset();
});
});
I looked for anyone else trying this and I've seen some answers on here that talk about the submit is being bound multiple times and I need to use unbind like $('#newimgform').unbind("submit").submit(); but that doesn't seem to do anything. I can't use any flash uploaders or anything so this has to be pure html/javascript/php.
You can move out the iframe load handler because it need not be added every time you upload a file. And also you can optimize your code like this.
$("#newupload").change(function() {
$('#newimgform').attr({
action: "uploadPicture.php",
method: "post",
MAX_FILE_SIZE: 5242880,
enctype: "multipart/form-data",
encoding: "multipart/form-data",
target: "postframe",
}).submit();
});
$("#postframe").load(function() {
var iframeContents = jQuery.parseJSON($(this.contentDocument).find('body').html());
alert(iframeContents.filename);
$("#newimgform")[0].reset();
});
Bind the load event handler outside the change event handler. As it is, everytime you change the value of #newupload, a new event handler is bound to the #postframe element:
$("#postframe").load(function() {
var iframeContents = jQuery.parseJSON($(this.contentDocument).find('body').html());
alert(iframeContents.filename);
$("#newimgform")[0].reset();
});
$("#newupload").change(function() {
$(this).attr("action", "uploadPicture.php")
.attr("method", "post")
.attr("MAX_FILE_SIZE", 5242880)
.attr("enctype", "multipart/form-data")
.attr("encoding", "multipart/form-data")
.attr("target", "postframe")
.submit();
});
You could alternatively unbind the load event handler each time it runs, but this seems unnecessary in your case. $(this).unbind('load'); is all you would have to add to the load event handler.
Also you can optimize this, a lot. You are using the same selector over and over, when in jQuery we chain function calls.

Categories

Resources