I am new to web development, and am trying to set up a practice form to learn form validation. I am following Bootstrap's doc for Custom Styles to handle those with accessibility issues that use screen readers, and to standardize the validation appearance to users across different browsers.
I have set up a basic form as well as am trying to create a JavaScript function using jQuery to handle the validation. I feel like I am almost there, but still do not have the validation working as the Bootstrap demo displays.
index.html
<form id="signup-form" novalidate>
<div class="form-group">
<h1>Sign Up</h1>
<p>Use this form to enter your name and email to sign up.</p>
</div>
<!-- Name -->
<div class="form-group">
<div class="row">
<div class="col">
<label for="firstNameInput">Name</label>
<input type="text" class="form-control" id="firstNameInput" placeholder="First name" required>
<div class="valid-feedback">
Looks good!
</div>
</div>
<div class="col">
<label for="lastNameInput">Last</label>
<input type="text" class="form-control" id="lastNameInput" placeholder="Last name" required>
<div class="valid-feedback">
Looks good!
</div>
</div>
</div>
</div>
<!-- Email -->
<div class="form-group">
<label for="emailAddressInput">Email address</label>
<input type="email" class="form-control" id="emailAddressInput" aria-describedby="emailHelp" placeholder="name#example.com" required>
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
<div class="invalid-feedback">
Please provide a valid email.
</div>
</div>
<!-- Options -->
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="radio" name="Radios" id="type1RadioButton" value="option1" checked>
<label class="form-check-label" for="type1RadioButton">
Type 1 user
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="Radios" id="type2RadioButton" value="option2">
<label class="form-check-label" for="type2RadioButton">
Type 2 user
</label>
</div>
</div>
<!-- Submit Button -->
<div class="form-group">
Submit
</div>
</form>
script.js
$(document).ready(function() {
$("#submitButton").click(function() {
//Fetch form to apply custom Bootstrap validation
var form = $("#signup-form")
//alert(form.prop('id')) //test to ensure calling form correctly
if (form.checkValidity() === false) {
event.preventDefault()
event.stopPropagation()
}
form.addClass('was-validated')
})
})
The problem is that checkValidity() exists on the first form node, not the form.
Change this: form.checkValidity() === false
to this: form[0].checkValidity() === false
and it works: https://www.codeply.com/go/pUPBLzn6yL
$(document).ready(function() {
$("#submitButton").click(function() {
//Fetch form to apply custom Bootstrap validation
var form = $("#signup-form")
alert(form.prop('id')) //test to ensure calling form correctly
if (form[0].checkValidity() === false) {
event.preventDefault()
event.stopPropagation()
}
form.addClass('was-validated');
//Make ajax call here
})
})
More on Bootstrap 4 Validation:
Can't make the validation work in Bootstrap 4
Related
I have a problem setting up a form on my website.
I want to add two separate forms on my website, which i did, using some HTML & css.
Thoses forms need to send informations to a webhook -> it also works (since it's collected)
BUT as soon as i press submit, it redirect to the main page of the website, so no conversion (which is a shame) and a very bad input from me.
Please, lend me your intelligence, since i must be the best idiot there is.
<form name='myForm' data-form-id='IdFromWebhook' action='WebhookLink' method='post' onsubmit="return false">
<div class="row">
<div class="col-lg-12">
<div class="form-group text_box">
<label for='EMAIL_ADDRESS'>E-mail: </label><input id='insightly_email' name='email' type='text' required>
</div>
</div>
<div class="col-lg-6">
<div class="form-group text_box">
<label for='FIRST_NAME'>First name: </label><input id='insightly_firstName' name='firstName' type='text' required>
</div>
</div>
<div class="col-lg-6">
<div class="form-group text_box">
<label for='LAST_NAME'>Last Name: </label><input id='insightly_lastName' name='lastName' type='text' required>
</div>
</div>
<div class="col-lg-4">
<div class="form-group text_box">
<label for='Language__c'>Choose a language: </label>
<select id='insightly_language' name='language' required><option value='EN'>EN</option><option value='FR'>FR</option><option value='DE'>DE</option></select>
</div>
</div>
</div>
<!--Bouton d'envoi-->
<div style="display:flex;justify-content:center"><input class="btn_three" type='submit' value='Submit'></div></form>
Use event.preventDefault() this will stops redirect:
formReference.onsubmit = (event) => {
event.preventDefualt()
}
I stupidly found the right answer, i had to specify URLs for the success or error pages.
It was an insightly form.
In angular js, we have $submitted to populate error messages on submit click.
How can we display all validation errors on submit click in Angular
HTML:
<form #nameForm="ngForm" novalidate (ngSubmit)="saveNameForm(formModel)">
<div class="form-group">
<label for="inputName" class="form-control-label"> Name</label>
<input type="text" id="inputName" name="lotCode [(ngModel)]="formModel.name" #lotCode="ngModel" aria-describedby="nameHelp"
autocomplete="new-password" required>
<small id="nameHelp" class="text-danger" *ngIf="lotCode.invalid && lotCode.touched">Required</small>
</div>
<div class="form-group">
<label for="inputDescription" class="form-control-label"> Description</label>
<input type="text" id="inputDescription" name="desCode" [(ngModel)]="formModel.description" #desCode="ngModel" aria-describedby="descriptionHelp"
autocomplete="new-password" required>
<small id="descriptionHelp" class="text-danger" *ngIf="desCode.invalid && desCode.touched">Required</small>
</div>
<button type="submit">Submit </button>
</form>
Component:
export class AppComponent {
formModel: FormModel= new FormModel();
saveNameForm(formModel){
console.log(formModel)
}
}
export class FormModel {
name: string;
description:string;
}
https://stackblitz.com/edit/angular-rizsuy?file=src%2Fapp%2Fapp.component.ts
Here is the solution:
https://stackblitz.com/edit/angular-8jaaqz?file=src%2Fapp%2Fapp.component.html
You should use a variable to set submitted
if submitted then will display error
Angular uses the same form validation that native HTML5 does. Just do this in an Angular context. In the following example, we can use *ngIf to control the display of the messages, and .dirty and .touched to determine if the user interacted with the input.
Example from docs:
<input id="name" name="name" class="form-control"
required minlength="4" appForbiddenName="bob"
[(ngModel)]="hero.name" #name="ngModel" >
<div *ngIf="name.invalid && (name.dirty || name.touched)"
class="alert alert-danger">
<div *ngIf="name.errors.required">
Name is required.
</div>
<div *ngIf="name.errors.minlength">
Name must be at least 4 characters long.
</div>
<div *ngIf="name.errors.forbiddenName">
Name cannot be Bob.
</div>
</div>
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 ...
});
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;
}
});
Just add these two lines
var errorElements = document.querySelectorAll(".form-control:invalid");
$(errorElements[0]).focus();
after
event.stopPropagation();
Putting focus to the first invalid field will automatically scroll the page to that position i
in most of the browsers.
Sergej, this worked great!
I modified it as below so that checkboxes/radio buttons and drop-down menus are also detected.
var errorElements = document.querySelectorAll(".form-control:invalid, .form-check-input:invalid, .form-select:invalid");
I updated AngularJs version from 1.3 to 1.4.
It causes an error as,
Syntax Error: Token '{' invalid key at column 2 of the expression
[{{frmname}}.emailAddress.$error] starting at
[{frmname}}.emailAddress.$error].
It works perfectly in Angular 1.3
<form name="{{frmname}}">
<h1>My form name = {{frmname}}</h1>
<div class="field">
<label for="emailAddress">Enter your email address:</label>
<input type="email" name="emailAddress" ng-model="email" required />
<div ng-messages="{{frmname}}.emailAddress.$error">
<div ng-message="required">
You forgot to enter your email address...
</div>
<div ng-message="email">
You did not enter your email address correctly...
</div>
</div>
</div>
<input type="submit" />
</form>
FIDDLE
If you need to set your form name from a dynamic variable then you could use ng-form to validate your inputs inside the actual form.
Basic html:
<form name="{{formName}}" novalidate>
<ng-form name="emailError">
<div ng-messages="emailError.emailAddress.$error" style="color:maroon" role="alert">
<label for="emailAddress">Enter your email address:</label>
<input type="email" name="emailAddress" ng-model="email" minlength="5" required />
<div ng-messages="emailError.emailAddress.$error" style="color:maroon" role="alert">
<div ng-message="required">You did not enter a field</div>
</div>
</ng-form>
<input type="submit" />
</form>
Plunker: https://plnkr.co/edit/Q0ifmRXKkLfwKGNqv8p4?p=preview
Official documentation of ngForm: https://docs.angularjs.org/api/ng/directive/ngForm
Finally i got the solution,
Add a function for getting ng-messages attribute value.
<div ng-messages="getMessages('emailAddress')">
<div ng-message="required">
You forgot to enter your email address...
</div>
<div ng-message="email">
You did not enter your email address correctly...
</div>
</div>
Declare the function inside your controller or directive.
$scope.getMessages = function (el) {
return $scope.$eval($scope.frmname)[el].$error;
}
FIDDLE
I have read the parsley.js docs but I am still learning JQuery so it goes in one ear and out the other.
I think I need to add a custom event listener to achieve what I need, but I am really not sure, so some help would be appreciated.
I have a form with parsley.js embedded. The form works as expected but I have to add some functionality to the form.
How would I display an alert message (alert('no client side errors!');) to the user when all the client side errors have been cleared or when there are no client side errors when the form is submitted?
Here is an example of my form code:
<form id="name_details_form" class="form-horizontal" method="post" data-parsley-validate>
<div id="row_id_name_details_first_name" class="control-group">
<label for="id_name_details_first_name" class="control-label required">First Names:</label>
<div class="controls">
<input data-parsley-required="true" data-parsley-maxlength="200" data-parsley-required-message="This field is required." maxlength="200" type="text" id="id_name_details_first_name" name="name_details_first_name" class="input-xxlarge parsley-error" data-parsley-id="8581" dir="ltr"><span class="parsley-errors-list filled" id="parsley-id-8581" style="display: none;"><span class="parsley-required">This field is required.</span></span>
</div>
</div>
<div id="row_id_name_details_middle_name" class="control-group">
<label for="id_name_details_middle_name" class="control-label ">Middle Names:</label>
<div class="controls">
<input id="id_name_details_middle_name" type="text" name="name_details_middle_name" data-parsley-maxlength="200" maxlength="200" class="input-xlarge" data-parsley-id="7500"><span class="parsley-errors-list" id="parsley-id-7500" style="display: none;"></span>
</div>
</div>
<div id="row_id_name_details_last_name" class="control-group ">
<label for="id_name_details_last_name" class="control-label required">Last Names:</label>
<div class="controls">
<input data-parsley-required="true" data-parsley-maxlength="200" data-parsley-required-message="This field is required." maxlength="200" type="text" id="id_name_details_last_name" name="name_details_last_name" class="input-xxlarge parsley-success" data-parsley-id="7577" dir="ltr"><span class="parsley-errors-list" id="parsley-id-7577" style="display: none;"></span>
</div>
</div>
<hr />
<input class="btn-u btn-u-blue" type="submit" value="Add">
</form>
<script>
....
</script>
This code shows the alert message when the form is submitted and the all fields are valid.
<script>
$(document).ready(function() {
// bind parsley to the form
$("#name_details_form").parsley();
// on form submit
$("#name_details_form").on('submit', function(event) {
// validate form with parsley.
$(this).parsley().validate();
// if this form is valid
if ($(this).parsley().isValid()) {
// show alert message
alert('no client side errors!');
}
// prevent default so the form doesn't submit. We can return true and
// the form will be submited or proceed with a ajax request.
event.preventDefault();
});
});
</script>