vanilla-form-validator
v2.2.0
Published
a vanilla form validator
Readme
vanilla-form-validator.js
Inspired by: jquery-validation
Form Validator: provides validation for your existing forms, while making all kinds of customizations to fit your application really easy.
Demo - Features - Install - Usage - Options - Changelog - License
Demo
See the vanilla-form-validator.js demo.
Best practice
Use this library to validate a form and display the same style for error messages.
Features
- validate a form
- validate fields
- preconfigured and internationalizable error messages
- customize the submission form
- create custom validations
- accessible error messages (
aria-invalid,aria-describedby,aria-live, focus on the first invalid field) Accessibility - tested in Edge, Chrome, Firefox
Install
CDN via jsDelivr
<script src="https://cdn.jsdelivr.net/npm/vanilla-form-validator@latest/dist/vanilla-form-validator.min.js" type="text/javascript"></script>Download vanilla-form-validator.js and include the script in your HTML file:
<script src="vanilla-form-validator.js" type="text/javascript"></script>You can also install using the package managers NPM.
npm install vanilla-form-validatormodular code
import FormValidator from 'vanilla-form-validator'Usage
let commentForm = new FormValidator("#commentForm");or
let commentForm = new FormValidator(document.getElementById('commentForm'));or with options
let commentForm = new FormValidator("#commentForm", {
errorElement: 'label',
errorClass: 'error',
ignore: 'input[type="hidden"]'
});Where options is an optional parameter.
See below for a description of the available options and defaults.
Options
The default options are:
{
ignore: null,
fields: null,
errorElement: 'p',
errorClass: 'error',
errorFieldClass: null,
validFormClass: 'was-validated',
focusInvalid: true,
submitHandler: null,
messages: null
}Where:
ignoreis an optional string containing one or more selectors to match fields to ignore. This string must be a valid CSS selector stringfieldsis an array of custom fields validation Custom validationserrorElementis an html tag to display error messageerrorClassis a css class for display error messageerrorFieldClassis a css class added when a field is not validvalidFormClassis a css class added to the form on submit, removed if the form is not validfocusInvalidmoves the focus to the first invalid field when the submission fails (defaulttrue)submitHandleris a function to customize the submission form Customize the submission formmessagespreconfigured error messages, only the keys to override are needed Error messages
Fields are validated on focusout, keyup and change through listeners on the form, so fields added after the initialization are validated as well; disabled fields are skipped.
Call destroy() to remove the listeners.
Error messages
Preconfigured values are:
{
required: 'This field is required.',
remote: 'Please fix this field.',
email: 'Please enter a valid email address.',
url: 'Please enter a valid URL.',
date: 'Please enter a valid date.',
number: 'Please enter a valid number.',
phone: 'Please enter a valid phone.',
file: 'Please select a file.',
equalTo: 'Please enter the same value again.',
maxlength: 'Please enter no more than {0} characters.',
minlength: 'Please enter at least {0} characters.',
rangelength: 'Please enter a value between {0} and {1} characters long',
max: 'Please enter a value less than or equal to {0}.',
min: 'Please enter a value greater than or equal to {0}.',
range: 'Please enter a value between {0} and {1}',
regExp: 'Please enter a value matching the requested format.'
}Override solution:
one by one, below an example:
let messages = { required: 'Required field' //override default message } let signupForm = new FormValidator("#signupForm", { errorElement: 'label', messages: messages, });loading a json file
commentForm.loadMessages('localization/messages_es.json');let commentForm = new FormValidator("#commentForm", { errorElement: 'label', ignore: 'input[type="hidden"]' }); commentForm.loadMessages('localization/messages_es.json');The package contains a preconfigured set of json files in
test/localization(ar, de, es, fr, it, ru); the messages must be wrapped in amessagesobject, missing keys keep the default value:{ "messages": { "required": "Campo obbligatorio", "email": "Inserisci un indirizzo email valido" } }loadMessagesreturns aPromiseresolved when the messages are loaded.Set on field the attribute
data-error-message<p> <label for="ccomment">Your comment (required)</label> <textarea id="ccomment" name="comment" required data-error-message="Custom error message"></textarea> </p>
Customize the position of error message
By default, the error message will be created after the field;
if you want to put the error message in another location,
simply create a html tag with id the field id or name if input type is radio or checkbox, append the -error
suffix (ex: id="cemail-error") and hide style="display: none;"
<p>
<label for="cemail">E-Mail (required)</label>
<input id="cemail" type="email" name="email" required />
</p>
<label id="cemail-error" class="error" style="display: none;"></label>The error element can be anywhere in the page (ex. after the form, to keep inline layouts intact) as long as it doesn't belong to another form.
Accessibility
The validator keeps the fields and the error messages readable by assistive technologies:
- an invalid field gets
aria-invalid="true", removed when the field becomes valid (on radio/checkbox groups, on every field of the group); - the id of the error element is added to the
aria-describedbyof the field while the error is displayed, preserving the other ids already present (ex. a hint); - the error element gets
aria-live="polite", so the message is announced when it appears or changes; if the error element is already in the page with its ownroleoraria-livethey are left untouched; - when the submission fails the focus is moved to the first invalid field (disable it with
focusInvalid: false).
The form gets the novalidate attribute, so the native browser messages are replaced by the validator ones: keep a visible (or visually hidden) <label> on every field.
Customize the submission form
Create a function on submitHandler property, it receives the form and the button that triggered the submission (if any)
let signupForm = new FormValidator("#signupForm", {
submitHandler: function (form, submitter) {
console.log('remote action')
}
});Without submitHandler the form is submitted natively, including the name/value of the submit button.
Custom validations
on input fields it's possible to use the pattern attribute (as in HTML, the expression must match the whole value)
for other fields or cases add an array of fields:
let signupForm = new FormValidator("#signupForm", {
fields: [
...
]
})fields configuration:
nameis the name of the fieldrulesis an array of object to configuremethodavailable methods are:equalTo, minlength, maxlength, rangelengthor javascriptfunction(fieldValue, field)returningtrueif the value is validfieldis a css selector to find a field, this option is used byequalTomethodminis min integer value used byminlength, rangelength(0is allowed)maxis max integer value used bymaxlength, rangelength(0is allowed)errorMessageis an optional error message
Preconfigured validations are: equalTo, minlength, maxlength, rangelength
These rules: minlength, maxlength, rangelength are applicable on input text,radio,checkbox,file, textarea and select fields
Example of preconfigured validation:
{
name: 'confirm_password',
rules: [
{
method: 'equalTo',
field: '#password'
}
]
},
{
name: 'minselect',
rules: [
{
errorMessage: 'Please select 2 elements.',
method: 'minlength',
min: 2
}
]
},
{
name: 'maxfiles',
rules: [
{
errorMessage: 'Please select max 2 files.',
method: 'maxlength',
max: 2
}
]
},
{
name: 'topic2',
rules: [
{
errorMessage: 'Please select 1 or 2 topics',
method: 'rangelength',
min: 1,
max: 2
}
]
}Example of custom validation:
{
name: 'username',
rules: [
{
errorMessage: 'Username already in use',
method: function (fieldValue, field) {
console.log('remote validation', fieldValue);
return true;
},
}
]
}A custom method can also return a Promise<boolean> (ex. a remote check): the error is displayed when the promise resolves
(a rejected promise is considered invalid) and the form is submitted only after all the pending checks are resolved.
Fields are validated on every keyup too, so consider caching or debouncing the remote calls.
{
name: 'username',
rules: [
{
errorMessage: 'Username already in use',
method: function (fieldValue, field) {
return fetch('/api/username-available?u=' + encodeURIComponent(fieldValue))
.then(response => response.json())
.then(data => data.available);
},
}
]
}When the field referenced by equalTo changes, the dependent field is validated again.
Migration from v1 to v2
Refactor the validation logic to use fields instead of rules in FormSettings to improve clarity and hierarchy, add more validations to each fields with their own error message.
before:
let signupForm = new FormValidator("#signupForm", {
rules: [
{
fieldName: 'confirm_password',
errorMessage: 'Password not match',
validation: {
method: 'equalTo',
field: '#password'
}
}
]
})after:
let signupForm = new FormValidator("#signupForm", {
fields: [
{
name: 'confirm_password',
rules: [
{
method: 'equalTo',
field: '#password',
errorMessage: 'Password not match'
}
]
}
]
})rulesis removed, usefieldsinsteadrules -> fieldNameis removed, usefields -> nameinsteadrules -> validationis removed, usefields -> rulesinsteadrules -> errorMessageis removed, usefields -> rules -> errorMessageinsteadrules -> method: 'custom'is removed, usefields -> rules -> method: function(fieldValue, field) {}instead
Changelog
To see what's new or changed in the latest version, see the changelog
License
vanilla-form-validator.js is licensed under The MIT License (MIT) Copyright (c) 2025 Simone Miterangelis
This license is also supplied with the release and source code. As stated in the license, absolutely no warranty is provided.
