When using HTML form validation, having an invalid input value in a form will halt submission of that form. How can I detect that the user attempted a failed form submission? The form's onsubmit handler does not fire when submission is halted by validation failure.
I'm currently listening for keypress and click events on the submit button to detect submit attempts. Is there a better way of detecting a failed form submission?
A simple way to get around this is to add an event listener to each input in the form to see when it has been prevented from submitting. The 'invalid' event should do everything you need.
Example
Array.prototype.slice.call(document.querySelectorAll("[required]")).forEach(function(input){
input.addEventListener('invalid',function(e){
//Your input is invalid!
})
});
More info here
http://www.html5rocks.com/en/tutorials/forms/constraintvalidation/
I suggest you to use noValidate property. You can turn off default validation, and run it manually within onsubmit method
var form = document.getElementById("myForm");
form.noValidate = true; // turn off default validation
form.onsubmit = function(e) {
e.preventDefault(); // preventing default behaviour
this.reportValidity(); // run native validation manually
// runs default behaviour (submitting) in case of validation success
if (this.checkValidity()) return form.submit();
alert('invalid'); // your code goes here
}
you can check it here: https://jsfiddle.net/titulus_desiderio/Laon29f3/
Building on #Titulus' code above, here's how I would do it in jQuery; you can adapt this to native events if need be.
$('form-selector').on('submit', function(event) {
// Don't do anything if constraint validation isn't supported by the browser.
if (
!('checkValidity' in this) ||
// In the unlikely case this is a property but not actually a function.
// Hypothetically, a botched polyfill could do this; it pays to be careful
// and build resilient code.
typeof this.checkValidity !== 'function'
) {
return;
}
if (this.checkValidity() === true) {
// Valid values code.
} else {
// Invalid values code.
// Leave this until the last possible moment in the handler in case there's
// an error in any of the handler code to reduce the chances of a broken
// form where the submit does nothing. If an exception is thrown before
// this, the browser shouldn't get this far, (hopefully) allowing the basic
// form to still work.
event.preventDefault();
}
});
// Tell the browser to not validate automatically, as that would prevent submit
// from being triggered. We prevent the submission above if form doesn't pass
// validation. This is here in case there's an error in the preceding code, so
// this (hopefully) doesn't get applied in that case and browser validation
// takes place as a fallback.
this.noValidate = true;
Related
I use the following javascript code to do some checks before a form is submitted:
$('form').submit(function(e){
var is_error = false;
// do certain checks and if some of them fail set is_error = true
if(!is_error)
return;
e.preventDefault();
});
This works perfectly and everything is fine actually.
However, I found out that this function is not necessarily always called on a form submit. (I was not able to reproduce this behavior by myself but I saw that on my error logs).
This is what I did to get this information:
I added an hidden input field to the form:
<input id="input-is_used_function" type="hidden" name="is_used_function" value="0" />
And i also adjusted the javascript the following way:
$('form').submit(function(e){
var is_error = false;
// do certain checks and if some of them fail set is_error = true
$('#input-is_used_function').val(1);
if(!is_error)
return;
e.preventDefault();
});
After the submit I logged all transmitted POST vars and I found out that 'is_used_function' is sometimes 0, which means that the jQuery submit function has never been called.
Does somebody has a solution for this or at least a hint on how this behavior happens?
Best,
Freddy
I am trying to use the jQuery validation plugin with tinyMce but I am having a small problem.
By default the validation plugin has the following behavior: initially every field is marked as valid and the validation is lazy i.e. the error isn't shown until the user enters a value and moves away from the field. Once a field is marked as invalid, it is eagerly validated which means the validation is done on every key stroke.
I am having difficulty simulating this behavior for the TinyMCE field. If I use the onChange method the validation is always done on focus out. If I use the onKeyDown method, validation is done on every key stroke, even if the user is changing the field for the first time.
Is there some way I can use a combination of onChange and onKeyDown in order to mimic the default behavior of jQuery validation plugin? Here is the code that I currently have:
function(ed) {
ed.onChange.add(function(ed, e) {
tinyMCE.triggerSave();
jQuery('#'+ed.id).valid();
});
}
In case I am not making sense you can read how the validation plugin behaves here.
Thanks in advance!
I think you're going to have to have a valid state variable
Something like this
function(ed) {
var validState = true;
ed.onKeyDown.add(function(ed, e) {
if (validState) {
return
}
else {
// check if new content is valid
validState = jQuery('#'+ed.id).valid();
}
}
ed.onChange.add(function(ed, e) {
validState = jQuery('#'+ed.id).valid();
if (validState){
tinyMCE.triggerSave();
}
});
}
Note this is just some sample code. I haven't verified that this will work
I use a system that captures visitors information via a form. I can't edit the code of the form validation scripts. I am trying to see if I can check upon clicking on the submit button, before the form submit sends the person to the response URL if the validation was passed.
The "submit" calls the function "formSubmit()", if validation is passed myFormIsValid() is returned. If not, then return false to the form.
Like this:
function formSubmit(elt) {
if (!myFormIsValid()) {
return false;
}
I want to know if validation was passed before allowing the form to move forward and do something like setting a variable value so I can tell Google Analytics that the form was successfully submitted. Is there a way to setup a "listener" to the results of the formSubmit function before it is called? I can put the code on the header or footer and I can use jQuery.
You can handle the submit before it reaches it's destination with an event handler.
jQuery.submit()
$(function () {
$("#MyForm").submit(function (e) {
if (!$(this).valid()) {
e.preventDefault(); // prevents the form from submitting.
return;
}
// you can do things here or just let it continue submitting.
});
});
I wrote a jquery plugin for validating forms. It bounds itself to the $('element').Submit event to trigger the validation (the bind is inside the plugin). Somehow like this:
// pseudocode
jquery.rdy {
$('form').validate(); //binding the plugin
}
Inside of the validate plug I bind the validation to the submit
//pseudocode
[...]
$().submit(function () {
validating... //returning true/false
if (false) {
return false //prevent submit form
}
}
[...]
So and now my question is how can I bind (in other js scripts for example) other stuff to the submit but just if a validation is done.
so like this
$('form').submit(function () {
if (validate plugin was executed) {
//do stuff like check if validation was returning a true and now do something else
}
}
Hopefully I descriped it right ...my english is not the best but I tryed to be as concrete s possible (and i hope, pseudocode is a right approach as well)
// EDIT: make the problem more concrete:
I'm trying to figure out a way to solve the following problem: (its very out of the context but the problem is exactly there..)
I have a submit event which is doing something depending on some code triggered in a another decleration.
$('element').submit(function () {
if ($(this).hasClass('foo')) {
// do something
}
});
$('element').submit(function () {
$(this).addClass('foo');
});
And now the first function is doing nothing cause it has been triggered before the second one. Is there a clean way to solve this. Maybe I need a timeout event (even I hate them)?
If you are using jQuery.Validate (which it looks like you are with the .validate() syntax), you can just call the isValid() method:
if (validate plugin was executed) {
can then be
if ($('form').isValid()) {
You can bind more functions to the form element with custom names.
$('form').bind('after_validation',function(){ console.log('hello'); });
And trigger them in your submit form function when you need it:
$('form').trigger('after_validation');
http://api.jquery.com/trigger/
Update:
You cannot change the order of your bound submit events without removing them .unbind('submit') and re-applying in the correct order. What you can do is use custom binds (see above) and trigger them exactly when you need it - like.. inside the submit function.
$('form').submit(function () {
//run validation
$('form').trigger('validation');
//did it pass validation?
if($(this).data('invalid')){
console.log('did not pass validation');
return false;
}
//passed validation - submit the form
return true;
});
//add validation to the "form"
$('form').bind('validation',function () {
//do validation on form...
if(false){
$(this).data('invalid',true);
}
});
//add another validator to the form, etc.
$('form').bind('validation',func...
Im using .data() to store variables to the 'form' element so you can access them down the chain.
This is the basis of what you need and can be applied to a custom jquery plugin to form custom named functions. eg. $().validator().
http://docs.jquery.com/Plugins/Authoring
I'm trying to send data from a form to an external script prior to submitting the form, yet I cannot seem to get the data to reach the external script unless I return false; on the form itself.
$(document).ready(function () {
// Handle Form-Submission
$("#mainForm").submit(function () {
// Reset Error Array
errors = new Array();
/* Validation Code Removed - Not Relevant */
// Check if errors exist
if (errors.length > 0) {
return false;
} else {
$("div.errors").html("");
$.post("post.php",{
"First Name": name_first.val(),
"Last Name": name_last.val(),
"Home State": home_state.val(),
"Primary Email": email_primary.val()
});
}
return false; /* Remove this line, and the $.post won't work. */
});
});
I ran into the exact same problem today. Like Marc says, it's because the ajax call is asynchronous. The simplest fix is to make it synchronous.
Use .ajaxSetup() before any ajax calls like such:
$.ajaxSetup({async: false});
Sending to two end points
I would try something like this instead of using async: true. Though it is notably more complicated, it would not freeze the interface.:
$(document).ready(function(){
// Handle Form-Submission
$("#mainForm").submit(function(e){
e.preventDefault();
var $form = $(this);
if($form.data('submitting')) return; // Avoid double submissions
$(':submit').attr('disabled','disabled'); // Disable the submit button
// Reset Error Array
errors = new Array();
/* Validation Code Removed - Not Relevant */
// Check if errors exist
if (errors.length > 0) {;
$(':submit').removeAttr('disabled'); // Enable the submit button
return false;
} else {
$("div.errors").html("");
$form.data('submitting',true); // Flag that a submission has started
$.post("post.php",{
"First Name":name_first.val(),
"Last Name":name_last.val(),
"Home State":home_state.val(),
"Primary Email":email_primary.val()},
function(){
// remove our special handler and submit normally
$form.unbind('submit').submit();
}
);
}
});
});
Original Answer
It seems your hangup is that you want to use $.post if JavaScript is enabled, but let the form function normally with JavaScript disabled.
However, since none of your JavaScript will run if it is disabled you don't have to worry about altering behavior in the submit function.
You can just leave your return false; statement, or use
$("#mainForm").submit(function(e){
// all your existing code
e.preventDefault();
}
That will keep the form from submitting normally and will instead using your $.post method when JavaScript is enabled. If it is disabled it will submit normally.
preventDefault is preferred to return false if you want event bubbling to continue as normal, but keep the default browser action from continuing. return false is the equivalent of calling e.preventDefault(); e.stopPropagation();