When form is validated, how to SCROLL to the first error instead of jumping?
JqueryJquery ValidateScrolltoJquery Problem Overview
I've seen many questions with variations on this theme, but I'm looking for the straightforward solution:
HTML form, jQuery validation, multiple fields are required. When the form is submitted, validation jumps to the first error and highlights it. To increase usability, I want to scroll to that first error field. But it keeps blowing up the validation entirely or throwing scrollTo errors.
I need to use the standard validation plugin (http://docs.jquery.com/Plugins/Validation) but any scroller would be fine, tho I had been trying with scrollTo (http://flesler.blogspot.com/2007/10/jqueryscrollto.html).
Sample code is at http://jsfiddle.net/DtgKQ/1/, any help is appreciated.
Jquery Solutions
Solution 1 - Jquery
Here's what you can do:
-
By default the validate plugin focuses the first erroneous element (in case there's any). Turn off the option
focusInvalid
by setting it tofalse
. -
The callback
invalidHandler
handler is executed when the form is invalid. You get access through the second parametervalidator
to the validator object and thus to the errorList array. You can then animate the scroll relatively to the first erroneous element.
Here's the code:
$("#commentForm").validate({
focusInvalid: false,
invalidHandler: function(form, validator) {
if (!validator.numberOfInvalids())
return;
$('html, body').animate({
scrollTop: $(validator.errorList[0].element).offset().top
}, 2000);
}
});
Solution 2 - Jquery
I dont like all the jQuery extentions so here is my solution to this problem:
if ($('#MYID').valid()) {
//dosomething();
} else {
$('html, body').animate({
scrollTop: ($('.error').offset().top - 300)
}, 2000);
}
Solution 3 - Jquery
just add this code to your themes javascript:
(function($) {
$(document).ready(function(){
//bmo scroll to not valid
$(".wpcf7").on('invalid.wpcf7',function(e){
$('html, body').animate({
scrollTop: $(".wpcf7-not-valid").first().offset().top-30
}, 2000);
});
});
})(jQuery);
Solution 4 - Jquery
For Anyone Using HTML5 Validation + Vanilla JavaScript:
Not a direct answer to this question, but as this is the main post that comes up when searching for this question, I figured I'd post my solution here for anyone who's looking as well!
I'm using this in my ReactJS project, but it should work in just about any vanilla ES6 JavaScript setting using modern browsers, as well.
function scrollToInvalid(form) {
const invalidInputs = Array.from(form.querySelectorAll(':invalid, .is-invalid [, .custom-invalid-selector]')); // set up so you can use any custom invalid classes you're adding to your elements, as well
invalidInputs.sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top); // sort inputs by offset from top of viewport (handles issues with multi-column layouts, where the first element in the markup isn't necessarily the highest on the page)
invalidInputs[0].scrollIntoView({ block: 'center', behavior: 'smooth' }); // scroll first (top) input into center of view, using smooth animation
}
function handleSubmit(e) {
const form = e.currentTarget;
if (form.checkValidity() === false ) {
// form is invalid, don't submit
e.preventDefault();
e.stopPropagation();
// scroll first invalid input into view
scrollToInvalid(form);
}
else {
// form is valid, handle submit...
}
}
<form onSubmit="handleSubmit">
...
</form>
Solution 5 - Jquery
Maybe you could check what input failed and take it's position (top) and use jQuery's scrollTop
$(window).scrollTop(errorPosition)
It seems that getting each error field isn't very easy to get (at least for me).
Search for errorPlacement
in the Validation plugin documentation. There is an example how to get each error field.
Solution 6 - Jquery
try this:
$( "input[type=submit]" ).click(function() {
event.preventDefault();
event.stopPropagation();
// console.log("test")
var errorElements = document.querySelectorAll(".input-validation-error");
for (let index = 0; index < errorElements.length; index++) {
const element = errorElements[index];
// console.log(element);
$('html, body').animate({
scrollTop: $(errorElements[0]).focus().offset().top - 25
}, 1000);
return false;
}
});
Solution 7 - Jquery
$("#create-form").validate({ // Set Focus on first invalid input
focusInvalid: false,
invalidHandler: function() {
$(this).find(":input.error:first").focus();
}
});