Ajax ignores html validation - javascript

$('#addProduct').click(function (e) {
$('#qty').attr('required', 'required');
$('#product_id').attr('required', 'required');
e.preventDefault();
var product_id = $('#product_id').val();
var data = $("#editOrderContent").serializeArray();
data.push(addProduct);
$.ajax({
type: 'POST',
dataType: 'JSON',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
url: $('#editOrderContent').attr('action'),
data: data,
success: function (html) {
if (html.error) {
$('.wrap_result')
.text(html.error)
.fadeIn(500).delay(3000).fadeOut(500);
}
else if (html.success) {
$('#summary').before(html.tdProduct);
$('#summary_qty').text(html.summaries['qty']);
$('#summary_price').text(html.summaries['price'] + ' $.');
$('#summary_sum').text(html.summaries['sum'] + ' $.');
$('#product_id').val('');
$('#qty').val(1);
}
}
});
});
These 2 fields has required attributes but ajax still completing even with empty values in these fields, also ajax ignores min value of #qty field
Why is this happening?

Use $('#formid').valid() method before making ajax request read more about .valid()

e.preventDefault tells the event NOT to perform it's default action of submitting the form.
You're then making the fields required. That's fine - but they'll only be checked on submit. The form isn't actually being submitted at any point, you've told it to prevent that action.
You need to add a $('#form').submit(); Or add required directly to the html markup.
EDIT: Much more code added to the question. This may no longer apply.

Related

JQuery prevent form from being submitted inside ajax [duplicate]

This question already has answers here:
How to stop form submit during ajax call
(7 answers)
Closed 2 years ago.
I am new to JQuery and ajax in general and I want to disable form submit after I get data from my controller back (I am using Asp.net core MVC). Thing is that even tho I cancel submit it submits anyways as shown bellow:
$("form").submit(function (e) {
var link = '#Url.Action("Action", "Controller")';
var args = {
arg1: Elem1.val(),
arg2: Elem2.val()
};
$.ajax({
type: "GET",
url: link,
data: args,
dataType: "json",
success: function (data) {
alert(data.canacess); //Shows False
if (data.canacess== true) {
AllEnable();
}
else { //Goes here
e.preventDefault(); //Dont do this
alert(data.erromessage); //Do this
}
},
error: function () {
alert("Error. Kontaktujte správce.");
return;
}
});
});
I think it has to do something with ajax because anywhere else in code it works.
Thanks for any help!
e.preventDefault() needs to be invoked within the scope of the submit function handler. Right now you're invoking it in the AJAX callback handler which is far too late to have any effect.
Is there any way that I can stop form from being submitted until I decide whether I submit it or not?
Yes. To do that you need to always call e.preventDefault() in order to stop the form submission so that you give the AJAX request time to execute and return a response. Then, based on that response, you can directly submit the HTMLFormElement object, note not the jQuery object, and send the form data to the specified action. Try this:
$("form").submit(function(e) {
e.preventDefault();
var form = this;
$.ajax({
type: "GET",
url: '#Url.Action("Action", "Controller")',
data: {
arg1: Elem1.val(),
arg2: Elem2.val()
},
dataType: "json",
success: function(data) {
if (data.canacess) {
AllEnable();
form.submit();
}
},
error: function() {
alert("Error. Kontaktujte správce.");
}
});
});
Also note that when using boolean values in conditions it's redundant to compare them to true/false. Similarly, the return in the error handler is redundant as it's the last statement in the function anyway.

How to Replace Form Without Triggering the Change Event?

I would like to validate a form with an AJAX request to the server and then swap the form html in the web browser with the form html from the server because this would be an easy implementation in theory. It is proving a nightmare though because the change event is triggered without the user interacting further after the first interaction which triggered the first change event. Consequently an infinite loop of AJAX requests to the server is happening.
The html form sits inside a div which has classes 'container mb-4'. This is the JS code -
var _cont = $('.container.mb-4')
var _form = $('.custom-form')
function ajax_validation(form) {
form.on('change', 'input, select, textarea', function() {
form_data = form.serialize()
$.ajax({
url: "/form/6/",
type: "POST",
data: form_data,
success: function(data) {
if(!(data['success'])) {
_cont.empty()
_cont.append(data['form_html'])
form = _cont.find('form')
ajax_validation(form)
}
},
error: function () {
form.find('.error-message').show()
}
});
})
}
ajax_validation(_form)
The change event I am assuming is triggered because the server returns a form input field with a different csrf token as the value to the previous input field - all other fields are the same. So an obvious solution would be to keep the same csrf token. But I want to understand why the JS code isn't working. I thought destroying the form would destroy the change event bound to it. So am at a loss to explain this infinite loop. How do I change this so I can just swap the form and not trigger another change event until the user really does change something?
It's not a good thing to use events in function no need to do that
Also your event here for input , select , textarea for serialize you need to select the closest() form
Try the next code
var _cont = $('.container.mb-4');
var _form = $('.custom-form');
_cont.on('change', 'form input,form select,form textarea', function() {
var ThisForm = $(this).closest('form');
var form_data = ThisForm.serialize();
$.ajax({
url: "/form/6/",
type: "POST",
data: form_data,
success: function(data) {
if(!(data['success'])) {
_cont.html(data['form_html']);
}
},
error: function () {
ThisForm.find('.error-message').show()
}
});
});
And logically if(!(data['success'])) { should be if(data['success']) {
First let's understand the issue that you have. You have a function called ajax_validation that is defining a change event on the form's elements which, on response will call ajax_validation. So, if any change happens on your elements, then a new request is sent to the server. So, if any value is changed, like a token, the request will be sent again. You could use a semaphore, like this:
var semaphore = true;
function ajax_validation(form) {
form.on('change', 'input, select, textarea', function() {
if (!semaphore) return;
semaphore = false;
form_data = form.serialize()
$.ajax({
url: "/form/6/",
type: "POST",
data: form_data,
success: function(data) {
if(!(data['success'])) {
_cont.empty()
_cont.append(data['form_html'])
form = _cont.find('form')
ajax_validation(form)
}
semaphore = true;
},
error: function () {
form.find('.error-message').show()
}
});
})
}
Something like this should solve your issue for the time being, but you should consider refactoring your code, because what you experience is well-known and is called callback hell.
Turns out the password field was coming back blank from the server - this django must do out of the box if the PasswordInput widget is used. So the form is replaced with a new form which lacks the password input from the before. The browser was then applying the autofill password value to the form which was triggering the change event.
This is my code now. It checks that the form_data about to be sent for validation really is different to before minus the csrf token which will be different.
It is based on Mohamed's answer -
var _cont = $('.container.mb-4');
var _form = $('.custom-form');
var prev_data = undefined
_cont.on('change', 'form input,form select,form textarea', function() {
var ThisForm = $(this).closest('form');
var form_data_wo_csrf = ThisForm.find("input, textarea, select").not("input[type='hidden']").serialize()
if(form_data_wo_csrf == prev_data) {
return
}
var form_data = ThisForm.serialize()
$.ajax({
url: "/form/6/",
type: "POST",
data: form_data,
success: function(data) {
if(!(data['success'])) {
_cont.html(data['form_html']);
prev_data = form_data_wo_csrf
}
},
error: function () {
ThisForm.find('.error-message').show()
}
});
});

Ajax after ajax request, submit form normal way

I have ajax request:
<script>
$("#abc_form_submit").click(function(e) {
e.preventDefault();
//........
$.ajax({
type: "POST",
url: url,
dataType: 'json',
data: $("#abc_form").serialize(), // serializes the form's elements.
success: function(data)
{
if(data.success == 'false') {
// show errors
} else {
// SUBMIT NORMAL WAY. $("#abc_from").submit() doesnt work.
}
}
});
return false; // avoid to execute the actual submit of the form.
});
</script>
And php
.....
return $this->paypalController(params, etc...) // which should redirect to other page
.....
How should i make that ajax request if success, submit form normal way, because now if I redirect (at PHP) its only return response, but i need that this ajax request would handle php code as normal form submit (if success)
Dont suggest "window.location" please.
I would add a class to the form to test if your ajax has already occured. if it has just use the normal click funciton.
Something like:
$('form .submit').click(function(e) {
if (!$('form').hasClass('validated'))
{
e.preventDefault();
//Your code here
$.post(url, values, function(data) {
if (success)
{
$('form').addClass('validated');
$('form .submit').click();
}
});
}
}
Why don't you use a result variable that you update after a succesful AJAX request?
<script>
$("#abc_form_submit").click(function(e) {
e.preventDefault();
// avoid to execute the actual submit of the form if not succeded
var result = false;
//........
$.ajax({
type: "POST",
url: url,
dataType: 'json',
async: false,
data: $("#abc_form").serialize(), // serializes the form's elements.
success: function(data)
{
if(data.success == 'false') {
// show errors
} else {
// SUBMIT NORMAL WAY. $("#abc_from").submit() doesnt work.
result = true;
}
}
});
return result;
});
</script>
I've had this issue before where I needed the form to submit to two places, one for tracking and another to the actual form action.
It only worked by submitting it programatically when you put the form.submit() behind a setTimeout. 500ms seems to have done the trick for me. I'm not sure why browsers have trouble submitting the form programatically when they are attempting to submit them traditionally, but this seems to sort it out.
setTimeout(function(){ $("#abc_from").submit(); }, 500);
One thing to keep in mind though once it submits, that's it for the page, it's gone. If you still want whatever processes are running on the page to run, you will need to set the target of the form to _blank so that it will submit in a new tab.

AJAX success callback only carrying out first function

I've got a simple form submission that upon success I've got an alert and a call to clear the form. I do get the alert, the info gets successfully added to the database, but the second call--for the form to clear, is not being carried out. I'm sure it's something simple I'm doing wrong, but I can't figure it out.
$('#contact_submit').click(function(e){
if ($("#submit_form_contact").valid()) {
var post_data = {
"name" : $('#name').val(),
"email" : $('#email').val(),
"inquiry" : $('#inquiry_dropdown option:selected').text(),
"message" : $('#message').val()
};
$.ajax({
type: "POST",
url: "process-contact.php",
data: post_data,
success: function(data) {
alert("Thank you for contacting us.");
$('#submit_form_contact').reset();
}
});
e.preventDefault();
}
Also, the submit button is just a button, not a submit input. Is it necessary to preventDefault()? I'm new at this.
jQuery doesn't have a .reset() method.
Do this instead:
$('#submit_form_contact')[0].reset();
This grabs the first DOM element, and invokes the native .reset(). If there's any chance the form won't be found, then test for the element.
var f = $('#submit_form_contact')[0];
if (f)
f.reset();
And of course you don't really need jQuery to get an element by ID, especially if you're not going to use any jQuery methods.
var f = document.getElementbyId('submit_form_contact');
if (f)
f.reset();
Another alternative would be to set the submit button as the context: of the ajax call, then use its form property.
$.ajax({
context: this,
type: "POST",
url: "process-contact.php",
data: post_data,
success: function(data) {
alert("Thank you for contacting us.");
this.form.reset();
}
});
this line can be used too
$("#submit_form_contact").trigger('reset');

jQuery override event.preventDefault()

I have a form that, when submitted, goes through the usual e.preventDefault() and sends an ajax request instead. However, if this ajax request returns a certain condition, I want the form to be submitted normally. How do I achieve this?
// Submit handler
$(".reserveer_form").submit(function(event){
event.preventDefault();
$.ajax({
url: $(this).attr("action"),
data: $(this).serialize(),
success: function(data) {
if($(".messagered",data).length > 0){
var errors = $(".messagered",data);
$(".gegevens").before(errors);
} else {
// SUBMIT THE FORM!
}
}
});
})
Invoke the native submit method on the form, so that it doesn't trigger the jQuery handler.
$.ajax({
context: this, // <-- set the context.
url: $(this).attr("action"),
data: $(this).serialize(),
success: function (data) {
if ($(".messagered", data).length > 0) {
var errors = $(".messagered", data);
$(".gegevens").before(errors);
} else {
this.submit(); // <-- submit the form
}
}
});
Since your comment says you change a form variable, you could start your submit handler by checking that same form variable. If it is changed, just return true. If not, continue with the current handler.
You can use the submit() method or forms:
$(".reserveer_form").submit(function(event){
event.preventDefault();
var form = this,
$form = $(form);
$.ajax({
url: $form.attr("action"),
data: $form.serialize(),
success: function(data) {
var errors = $(".messagered", data);
if (errors.length > 0){
$(".gegevens").before(errors);
} else {
form.submit();
}
}
});
})
However, this seems to be a strange ajax request. First, you send the form (serialized, via ajax) to the server, and when the response contains no errors you send it again? The server would process it twice (and act twice, depending on your form). Also, the user does not get a message that his input is already processed - he clicks "submit", and it always takes a time until it is visibly submitted (where he even could change some input).

Categories