Accessible and user-friendly HTML5 form validation library.
- Lightweight, no dependencies.
- Based on the HTML5 form validation api (with polyfills).
- Display error messages and validate inputs when it makes sense from an user perspective.
- Improve forms' accessibility by adding the relevant aria attributes.
- Supports "cached" templates to avoid duplicating error messages.
- Get GentleForm
- From the repo: GentleForm.min.js
- With bower:
bower install gentleform
- Include it:
<script src="path/to/GentleForm.min.js"></script>
- Add the required styles:
.is-hidden { display: none !important; }
Basic example:
<style>
.is-hidden { display: none !important; }
.is-invalid { border-color: red; }
.is-valid { border-color: green; }
</style>
<form>
<input type="text" name="firstname" required>
<div data-errors-for="firstname">
<div data-errors-when="valueMissing">This field is required.</div>
</div>
<button type="submit">Submit</button>
</form>
<script src="GentleForm.min.js"></script>
<script>new GentleForm('form', function onSubmit (event, isValid, data) {});</script>
<form>
<input type="text" name="firstname" required>
<div data-errors-for="firstname">
<div data-errors-when="valueMissing">This field is required.</div>
</div>
</form>
<script src="path/to/GentleForm.min.js"></script>
<script>new GentleForm('form', function (event, isValid, data) {});</script>
The first argument passed to GentleForm is a css selector targetting a form. The second one is a function to call on form submission. The callback receives three arguments:
event
- the submit event.isValid
- a boolean indicating if the form is valid or not.data
- an object containing the form's data.
So given the example above, considering that the firstname input has been filled with "joe", the data object would look like:
{
"firstname": {
"value": "joe",
"validity": {
"valid": false,
"customError": false,
"patternMismatch": false,
"rangeOverflow": false,
"rangeUnderflow": false,
"stepMismatch": false,
"tooLong": false,
"tooShort": false,
"typeMismatch": false,
"valueMissing": false
}
}
}
Name | Description |
---|---|
is-hidden | Used to hide error messages. |
is-changed | Added when the input's value change'd, meaning the user interacted with it. |
is-submitted | Added when the input has been submitted. |
is-valid | Added when the input is valid. |
is-invalid | Added when the input is invalid. |
Note: the inputs are validated in real time but only after the "is-changed" and/or "is-submitted" classes has been added. It means that an input won't have the class "is-valid" nor "is-invalid" until the user interact with it.*
Those classes are added to the form elements their selves. If you want to add them to an other element, you can use the "data-states-for" attribute.
<input type="text" name="firstname">
<div data-states-for="firstname"></div>
So now, every classes that are added to the firstname's input will be added to the div too.
<input type="text" name="firstname" required>
<div data-errors-for="firstname">
<div data-errors-when="valueMissing">This field is required.</div>
</div>
As you can see, the data-errors-for
attribute acts a bit like a switch statement.
The first thing is to declare what input it is related to by referencing it via its name (e.g data-errors-for="firstname"
).
Then, within this element, you can add error messages to display when one of the form element's validityState object property is set to true (e.g data-errors-when="valueMissing"
).
Here is the supported constraints:
badInput
indicates if the user has provided input that the browser is unable to convert.customError
indicates if the element's custom validity message has been set to a non-empty string by calling the element'ssetCustomValidity()
method.patternMismatch
indicates if the value does not match the specified pattern (e.g<input pattern="[a-z]">
).rangeOverflow
indicates if the value is greater than the maximum specified by the max attribute (e.g<input max="5">
).rangeUnderflow
indicates if the value is less than the minimum specified by the min attribute (e.g<input min="5">
).stepMismatch
indicates if the value does not fit the rules determined by the step attribute (that is, it's not evenly divisible by the step value).tooLong
indicates if the value exceeds the specified maxlength for HTMLInputElement or HTMLTextAreaElement objects (e.g<input maxlength="5">
).tooShort
indicates if the value exceeds the specified minlength for HTMLInputElement or HTMLTextAreaElement objects (e.g<input minlength="5">
).typeMismatch
indicates if the value is not in the required syntax (when type is email or url).valid
indicates if the element meets all constraint validations, and is therefore considered to be valid.valueMissing
indicates if the element has a required attribute, but no value (e.g<input required>
).
Actually the HTML5 form validation api is not fully supported, even by modern browsers. But don't worry, GentleForm internally uses flooz to manipulate the DOM and it has polyfills for those features.
To avoid duplicating the same error messages for every form elements, you can use the data-include
attribute.
<input type="text" name="firstname" required>
<div data-errors-for="firstname" data-include="form-errors"></div>
<input type="text" name="lastname" required>
<div data-errors-for="lastname" data-include="form-errors"></div>
<script type="text/gentle-template">
<div data-errors-when="valueMissing">This field is required.</div>
</script>
Those attributes are updated live:
aria-hidden
: added and set to true along with theis-hidden
class.aria-invalid
: added and set to true to invalid elements.
While those ones are added on GentleForm's instantiation:
aria-required
: added and set to true to required inputs.role=alert live=assertive atomic=true
: added to error messages ([data-errors-for]
).aria-describedby
: added to inputs that have related error messages (support multiple references).
There's nothing you need to do for the aria attributes to be added as long as you do not manipulate the form's DOM content.
Otherwise, if you need to add/remove form elements or change a required attribute you can call .refreshAria()
.
Here is an example of how you could do that:
<form>
<input type="text" required>
</form>
<script>
var form = new GentleForm('form');
setTimeout(function () {
document.querySelector('form').innerHTML += '<input type="email" required>';
form.refreshAria();
}, 1000);
</script>