Another form validation library! There are already some good ones out there, but most depend on other libraries, or require you to get your hands dirty. Use Simple Validations (JSV) when don't want to mess with any Javascript, CSS or dependencies (aren't forms painful enough already?) Think of it as enhanced HTML5 form validations.
- Validates as you type
- No dependency on any other library or framework (vanilla JS)
- Configures with HTML, using data attributes (write no JS, unless you want)
- No separate styling needed (unless you want to customize)
- Promise-based and debounced
- Supports async validations
- ES5-compatible, tested back to IE11
- Can be used for multiple forms on a page
- Only 10kb gzipped
- How it works
- Installation
- Quick Setup
- Validation Types
- Customizing Validation Messages
- Containers and Styling
- Form Configuration
- Field Configuration
- App Configuration
- Custom Validators
- Callbacks
- Testing
- Acknowledgements
JSV listens for input
, change
and focusout
events on each field in the form, and the submit
event on the form itself. Validations are triggered on each of those events. When all fields pass validation, the form is in a "valid" state and can be submitted.
To avoid you having to write any Javascript, JSV instantiates and attaches to form elements when the page is ready. JSV is intended for use with "traditional" server-side rendered HTML forms. So if you're using a framework or otherwise creating your forms with Javascript, it probably won't work.
Download the javascript file, or just include this script tag in your HTML:
<script src="https://unpkg.com/[email protected]/dist/js-simple-validations.js"></script>
Or install with npm:
npm install js-simple-validations --save-dev
Then import into your bundle with:
import SimpleValidations from 'js-simple-validations';
On your form(s) add this data-jsv-form="true"
to any form(s) you want to validate:
<form action="/processform" method="POST" data-jsv-form="true">
For each field in the form you want to validate, specify the field validation type(s) like data-jsv-validators="[TYPE]"
<input type="text" name="firstname" data-jsv-validators="require" />
Or apply multiple types like:
<input type="text" name="email" data-jsv-validators="require, email" />
That's all you need to do (unless you want to customize)
require
Input value exists and is not all whitespace.
<input type="text" name="firstname" data-jsv-validators="require" />
If require
is not specified, other validators will only trigger if there's a value entered, by design. So always use require
(with others, optionally) if you require some input in the field.
Inputted value is a properly-formatted email.
<input type="text" name="email" data-jsv-validators="email" />
url
Inputted value is a properly-formatted URL.
<input type="text" name="website" data-jsv-validators="url" />
number
Input is a number (decimals OK).
<input type="number" name="children" data-jsv-validators="number" />
length
Character length of the inputted value must be within a range. Specify character lengths in data-jsv-min
and data-jsv-max
.
<input type="text" name="username" data-jsv-validators="length" data-jsv-min="6" jsv-length-max="20" />
exact
There must be an exact number of characters entered. Specify in data-jsv-exact
.
<input type="text" name="username" data-jsv-validators="exact" data-jsv-exact="12" />
numberexact
Inputted value is a number this many characters long. Specify in data-jsv-exact
.
<input type="number" name="custno" data-jsv-validators="numberexact" data-jsv-exact="12" />
numberrange
Inputted value is a number is between (or equals) data-jsv-min
to data-jsv-max
<input type="number" name="age" data-jsv-validators="numberrange" data-jsv-min="1" data-jsv-max="120" />
contains
Input contains this string. Specify in data-jsv-contains
. Case-insensitive.
<!--make sure value contains (or IS) the word "twelve"-->
<input type="text" name="userInput" data-jsv-validators="contains" data-jsv-contains="twelve" />
zipcode
Inputted value is a properly-formatted US zip code (plus 4 optional, but validated if entered)
<input type="text" name="zipcode" data-jsv-validators="zipcode" />
phone
Inputted value is a properly-formatted phone number. This is a fairly liberal validation and will accept international numbers.
<!-- examples of valid input:
773-555-1212
(330) 555-1212
5045551212
+1-555-532-3455
+33-6-79-91-25-49
--!>
<input type="text" name="phone" data-jsv-validators="phone" />
creditcard
Inputted value is a properly-formatted credit card number using the Luhn Algorithm.
<input type="text" name="cardno" data-jsv-validators="creditcard" />
pattern
Validate input against a custom regular expression specified in data-jsv-pattern
.
<input type="text" name="birthdate" data-jsv-validators="pattern" data-jsv-pattern="^\d{4}\-\d{2}\-\d{2}$" placeholder="Enter a date in the format YYYY-MM-DD" />
compare
Compare inputted value against the value of another field. Specify the name
of the field to compare to in data-jsv-compare
. Case sensitive.
<!-- validates if the value entered into ConfirmPassword matches the value entered into Password-->
<input type="password" name="ConfirmPassword" data-jsv-validators="compare" data-jsv-compare="Password" placeholder="Confirm Password" />
dependent
Will not validate until fields specified in data-jsv-dependents
(comma delimited if more than one) are validated first.
<input type="password" name="ConfirmPassword" data-jsv-validators="dependent, require" data-jsv-dependents="Login, Password" />
expireddate
Checks if year, month and day (optional) combined field values are in the past. The year field in the form is specified with data-jsv-expiredate="year"
, month, data-jsv-expiredate="month"
and (optional) day data-jsv-expiredate="day"
. All get the expireddate
validator.
<select name="expirationMonth" data-jsv-validators="expireddate" data-jsv-expiredate="month">
<option value="">Select Month</option>
<option value="1">January</option>
...
</select>
<select name="expirationYear" data-jsv-validators="expireddate" data-jsv-expiredate="year">
<option value="">Select Year</option>
<option value="2019">2019</option>
...
</select>
Field values should be numbers like "12" rather than names like "December" (therefore, best used with select boxes).
An AJAX GET request is made to the endpoint in data-jsv-ajax-endpoint
. The field's name is used as the key, and the input as its value.
If the JSON response has the key specified in data-jsv-ajax-key
and that matches data-jsv-ajax-value
, the field validates.
<!--generates an AJAX request to /username_check?Login=[input]
validates if the JSON response looks like:
{ "usernameAvailable": true }
-->
<input
type="text"
name="Login"
data-jsv-validators="ajax"
data-jsv-ajax-endpoint="/username_check"
data-jsv-ajax-key="usernameAvailable"
data-jsv-ajax-value="true"
/>
If data-jsv-ajax-value
is left empty, the input is used to match.
requiremin
Used to validate radio buttons and checkboxes (multiple form elements with the same name
). Validates that the minimum number specified in data-jsv-min-selected
have been selected. All elements with the same name
should have the requiremin
validator and the same number in data-jsv-min-selected
.
<!--Validates that both checkboxes have been checked-->
<label>Agree to terms of service?</label>
<input
data-jsv-validators="requiremin"
data-jsv-min-selected="2"
type="checkbox"
name="terms"
value="1"
/>
<label>Agree to more stuff?</label>
<input
data-jsv-validators="requiremin"
data-jsv-min-selected="2"
type="checkbox"
name="terms"
value="2"
/>
You can customize the error message for each validator in the field itself. The format is:
data-jsv-field-error-[validator]="[custom error message]"
Example of a custom error messages for validators on a credit card field:
<input
name="cardNumber"
type="text"
data-jsv-validators="require, creditcard"
data-jsv-field-error-require="Please enter a credit card number (no spaces)"
data-jsv-field-error-creditcard="Please check your credit card number"
/>
Looks like this on invalid input:
JSV applies containers and styles automatically. There's nothing you need to do, the exception being radio buttons and some checkboxes (see below).
You can override the styles if you wish. Each form gets an error container with the class validate-form-error-message
. Each input field is wrapped in a validation container with the class validate-input
so that the it can be styled as valid or invalid. A sibling container with class validate-field-error-message
immediately follows, where error messages appear. The CSS is included but can be overridden in your own stylesheet if desired.
* Multiple form elements with the same name
- like radio buttons or multi-value checkboxes - need to have the error message container and validation container (optional) added to the form manually.
Put this container where you want to target your error messages for the group of elements:
<div class="validate-field-error-message" id="[YOUR ID NAME]"></div>
Then link each element of the group to the message target by adding the message target's ID to the element's data-jsv-message-target data attribute:
data-jsv-message-target="[YOUR ID NAME]"
Below is a full example of a multi-value checkbox with the error message and the optional validation container specified:
<!-- Example of multi-value checkbox inputs that have the
validation and error containers added. Note addition
of the ".validate-input" and ".validate-field-error-message"
elements. Link the inputs to the containers by specifying
the IDs in "data-jsv-message-target" and "data-jsv-validation-target"
data attributes. -->
<div class="validate-input" id="checkboxvalidate">
<input
data-jsv-validators="requiremin"
data-jsv-min-selected="2"
id="test-terms-service"
data-jsv-message-target="checkbox-invalid"
data-jsv-validation-target="checkboxvalidate"
type="checkbox"
name="terms"
value="yes"
/>
<label for="test-terms-service">Agree to terms of service?</label>
<input
data-jsv-validators="requiremin"
data-jsv-min-selected="2"
id="test-terms-service-more"
data-jsv-message-target="checkbox-invalid"
data-jsv-validation-target="checkboxvalidate"
type="checkbox"
name="terms"
value="more"
/>
<label for="test-terms-service-more">Agree to more stuff?</label>
<div class="validate-field-error-message" id="checkbox-invalid"></div>
</div>
Looks like:
The following data attributes can be added to the <form>
tag
Attribute | Description |
---|---|
data-jsv-form="true" (required) |
Attaches JSV to the form |
data-jsv-disable-icons="true|false" |
Toggles field validation icons for all elements of the form |
data-jsv-disable-invalid="true|false" |
Toggles disabling of the <button> element for valid and invalid form states |
data-jsv-form-invalid-message="[MESSAGE]" |
Message to show in the form-level error container upon submit of an invalid form |
data-jsv-form-incomplete-tooltip="[MESSAGE]" |
Message that appears in a tooltip when customer hovers the <button> element of an invalid form |
data-jsv-submit-handler="[JAVASCRIPT FUNCTION NAME]" |
If you want to handle submit of the form with Javascript, the specified function will be called upon submit of a valid form. It's called with the arguments: event , form (the entire form element) and the string 'valid '. If no function is specified, the form submits normally. |
data-jsv-form-invalid-callback="[JAVASCRIPT FUNCTION NAME]" |
If specified, the function is called when a form is submitted but is not valid. Arguments: event , form (the entire form element) and the string 'invalid '. |
data-jsv-form-valid-callback="[JAVASCRIPT FUNCTION NAME]" |
If specified, the function is called when a form becomes valid. If used, be prepared for the possibility that it can be called many times. Also, this is not to be used as a submit handler. Arguments: event , form (the entire form element) and the string 'valid '. |
The following attributes can be added to the form field elements (like <input>)
:
Attribute | Description |
---|---|
data-jsv-validators="[VALIDATORS]" (required) |
One, or a comma-separated list of the validations to add to this field. If multiple, they are evaluated left to right |
data-jsv-field-error-[VALIDATOR]="[MESSAGE]" |
Specify the error message for a particular validator on this field. See Customizing Validation Messages. |
data-jsv-message-target="[ID]" |
Specify a target for field invalid error messages. Required for use with radio buttons and multi-value checkboxes, but can also be used to override default automatic behavior on any field. Details |
data-jsv-validation-target="[ID]" |
Specify a target for field validation container. Recommended for use with radio buttons and multi-value checkboxes, but can also be used to override default automatic behavior on any field. Details |
data-jsv-disable-icon="true|false" |
Toggles disabling of valid or invalid icon for this field only. |
data-jsv-debounce="[MILLISECONDS]" |
Wait for [MILLISECONDS] before triggering any validations on this field. |
data-jsv-field-invalid-callback-[VALIDATOR]="[JAVASCRIPT FUNCTION NAME]" |
If specified, the function is called when [VALIDATOR] is triggered but is invalid. Arguments: event , form , name , name of the last validation performed, The string 'invalid ', the error message. |
data-jsv-field-valid-callback-[VALIDATOR]="[JAVASCRIPT FUNCTION NAME]" |
If specified, the function is called when [VALIDATOR] is triggered and returns valid. Arguments: event , form , name , name of the last validation performed, The string 'valid '. |
Further configuration of JSV can be done by declaring a validateOptions
object in the window (before JSV instantiates), with a 'cfg
' key:
var window.validateOptions = {
cfg: { // config options }
};
Any configuration settings can be customized, though there are only a few that make sense to change:
Config Key | Description |
---|---|
"useCss": true|false |
Toggles injection of the built-in CSS for UI valid/invalid states. If you want to add your own CSS to the window, set to false |
"useTooltip": true|false |
Toggles enabling of a tooltip that appears over the <button> element when the form is in an invalid state. |
"isValidColor": "[HEX COLOR]" |
Customize the color for the field valid state. Default: #13bd3a (green) |
"isInvalidColor": "[HEX COLOR]" |
Customize the color for the field valid state. Default: #ff0000 (red) |
"isValidIcon": "[UNICODE]" |
Customize the field valid icon unicode character. Default: \\2713 (checkmark) |
"isInvalidIcon": "[UNICODE]" |
Customize the field invalid icon unicode character. Default: \\2716 (heavy multiplication X) |
"fieldErrorFont": "[FONT DECLARATION]" |
Use unified CSS font "shorthand" format. Default: normal 12px Helvetica, Arial, sans-serif |
"formShowMessages": true|false |
If false, no form-level error messages will be shown when a form submit is attempted on an invalid form. |
"safeStringInput": true|false |
If true, all inputted values are passed through a basic XSS sanitizer. |
"safeEndpoints": true|false |
If true, endpoints can only be relative urls (i.e. no http:// allowed) |
"ajaxTimeout": [MILLISECONDS] |
Time out an AJAX request after [MILLISECONDS]. Default: 8000 |
"debounceDefault": [MILLISECONDS] |
Wait time before any validations are triggered. Allows user to type without being bothered by error messages. Default: 300. |
NOTE If modifying config settings other than the ones above: form and field-level configuration data attributes always takes precedence over config settings.
You can write your own validators for JSV by declaring a validateOptions
object in the window (before JSV instantiates), with a 'customValidators
' key:
var window.validateOptions = {
cfg: { // any app config options (see previous section) },
customValidators: {
"[VALIDATOR NAME]": { // name of custom validator
"events": [], // experimental - array of events this validator should fire on, [] = default
"validator": function(field, value, validator) { // required
return new Promise(function(resolve, reject) { // required
// start custom validator code
if (true) {
resolve(); // required();
} else {
reject("[MESSAGE]"); // required, include message in reject
}
// end custom validator code
});
}
}
}
};
Validations are promises, so the custom validation must also be a promise with a resolve
and reject
. See the bottom of the demo form for a working example of a custom validator.
Callbacks to custom window functions can be configured for the following events:
- Field validator returns invalid
- Field validator returns valid
- Form becomes valid
- Form submit occurs, form is invalid
- Form submit occurs, form is valid
See form and field configuration to see how to specify callback functions, and how they are triggered. Also see examples of usage at the bottom of the demo form.
JSV listens for for and prevents the form submit
event to perform a final validation. If the form is valid, it continues submit
and the submission happens using the default method
and action
on the form
Use cases
AJAX form submit - To use AJAX to submit the form, you'll want to configure data-jsv-submit-handler="[FUNCTION]"
on the <form>
element. When the form submit
happens and the form is valid, the function specified in data-jsv-submit-handler
is called with the arguments: event
object, form
object and the string 'valid
'.
Username does not exist - Let's assume you're working on a user login form and you want to set up an AJAX validator to check that the username entered exists before the form is even submitted. A potential use for the "field invalid" callback on the ajax validator is: if the username does not exist, call a function that performs UI changes to direct the user to the sign-up form.
There is an E2E test suite that uses Jest and Puppeteer. To perform the tests on the demo form, you can run the following commands:
git clone https://github.com/tarponjargon/js-simple-validations.git
cd js-simple-validations
npm install
npm test
The idea behind JSV is to basically mimic some of the functionality of ember-cp-validations using vanilla JS.