I am using Bootstrap 4
and i am stopping form submission if any of the fields are invalid with the below script.
I am trying to figure out (with no success so far) what code do i need to add after the "event.stopPropagation();
" in order to make the form scroll to the first invalid field that was found.
Appreciate your help, thanks.
Form:
<form class="needs-validation" novalidate action="search.php" id="firstform" method="post" >
Prevent submission if invalid:
<script>
// Example starter JavaScript for disabling form submissions if there are invalid fields
(function() {
'use strict';
window.addEventListener('load', function() {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function(form) {
form.addEventListener('submit', function(event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
</script>
Found the below code but couldn't find a way to embed it into the "disabling form submissions" script or use it as a standalone script:
$("#firstform").validate({
focusInvalid: false,
invalidHandler: function(form, validator) {
if (!validator.numberOfInvalids())
return;
$('html, body').animate({
scrollTop: $(validator.errorList[0].element).offset().top
}, 2000);
}
});
You should use the input.form-control:invalid
pseudo selector that is added to the elements you’ll see the :invalid
and :valid
styles applied to your form controls.
Although using custom validation you have to look for a lot of things that this article
can cover up for you.
We will use the above selector document.querySelectorAll("input.form-control:invalid");
to get all the error fields list and scroll to the first error element in the form in case there are multiple errors.
See a demo below.
// Example starter JavaScript for disabling form submissions if there are invalid fields
(function() {
'use strict';
window.addEventListener('load', function() {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function(form) {
form.addEventListener('submit', function(event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
var errorElements = document.querySelectorAll(
"input.form-control:invalid");
errorElements.forEach(function(element) {
element.parentNode.childNodes.forEach(function(node) {
if (node.className == 'valid-feedback') {
node.className = 'invalid-feedback';
node.innerText =
'Please choose a Gender';
}
});
});
$('html, body').animate({
scrollTop: $(errorElements[0]).offset().top
}, 2000);
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
input[type=text],
input[type=email],
input[type=number],
textarea,
fieldset {
/* required to properly style form
elements on WebKit based browsers */
-webkit-appearance: none;
width: 100%;
border: 1px solid #333;
margin: 0;
font-family: inherit;
font-size: 90%;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<form class="needs-validation" novalidate>
<div class="form-row">
<div class="col-md-4 mb-3">
<label for="gender">Male</label>
<input id="gender_male" type="radio" name="gender" class="form-control col-sm-2" required>
<label for="gender">Female</label>
<input id="gender_female" type="radio" name="gender" class="form-control col-sm-2">
<label for="gender">Other</label>
<input id="gender_other" type="radio" name="gender" class="form-control col-sm-2">
<div class="valid-feedback">
Looks good!
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-4 mb-3">
<label for="validationCustom01">First name</label>
<input type="text" class="form-control" id="validationCustom01" placeholder="First name" value="Mark" required>
<div class="valid-feedback">
Looks good!
</div>
</div>
<div class="col-md-4 mb-3">
<label for="validationCustom02">Last name</label>
<input type="text" class="form-control" id="validationCustom02" placeholder="Last name" value="Otto" required>
<div class="valid-feedback">
Looks good!
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-4 mb-3">
<label for="validationCustomUsername">Username</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroupPrepend">@</span>
</div>
<input type="text" class="form-control" id="validationCustomUsername" placeholder="Username" aria-describedby="inputGroupPrepend" required>
<div class="invalid-feedback">
Please choose a username.
</div>
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-6 mb-3">
<label for="validationCustom03">City</label>
<input type="text" class="form-control" id="validationCustom03" placeholder="City" required>
<div class="invalid-feedback">
Please provide a valid city.
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-3 mb-3">
<label for="validationCustom04">State</label>
<input type="text" class="form-control" id="validationCustom04" placeholder="State" required>
<div class="invalid-feedback">
Please provide a valid state.
</div>
</div>
<div class="col-md-3 mb-3">
<label for="validationCustom05">Zip</label>
<input type="text" class="form-control" id="validationCustom05" placeholder="Zip" required>
<div class="invalid-feedback">
Please provide a valid zip.
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-3 mb-3">
<label for="validationCustom05">Zip</label>
<input type="text" class="form-control" id="validationCustom05" placeholder="Zip" required>
<div class="invalid-feedback">
Please provide a valid zip.
</div>
</div>
</div>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="invalidCheck" required>
<label class="form-check-label" for="invalidCheck">
Agree to terms and conditions
</label>
<div class="invalid-feedback">
You must agree before submitting.
</div>
</div>
</div>
<button class="btn btn-primary" type="submit">Submit form</button>
</form>
If you are using jQuery and only supporting modern browsers (which is likely if you're using Bootstrap 4), you can use the following code to validate the form and scroll to the field with an error:
$('form#contact').submit(function(e) {
var form = $(this);
// HTML5 validility checker
if (form[0].checkValidity() === false) {
// not valid
form.addClass('was-validated');
$('html,body').animate({scrollTop: $('.was-validated .form-control:invalid').first().offset().top - 50},'slow');
e.preventDefault();
e.stopPropagation();
return;
}
// valid, do something else ...
});