Abide Validation
Abide is an HTML5 form validation library that supports the native API by using patterns and required attributes.
Setting Up Validation
To enable validation with Abide, add the data-abide
attribute to your form
element. Then add the required
attribute to each input that you want to require. Additionally, you can define a pattern
to define restraints on what users can input.
<form data-abide>
<div class="name-field">
<label>Your name <small>required</small>
<input type="text" required pattern="[a-zA-Z]+">
</label>
<small class="error">Name is required and must be a string.</small>
</div>
<div class="email-field">
<label>Email <small>required</small>
<input type="email" required>
</label>
<small class="error">An email address is required.</small>
</div>
<button type="submit">Submit</button>
</form>
Predefined Patterns
Abide has several patterns common validation patterns built into the library:
Name | Valid Example or Format |
---|---|
alpha | Foundation |
alpha_numeric | A1Sauce |
integer | -1 |
number | 2937 |
card | visa, amex, mastercard |
cvv | 384 or 3284 |
contact@get.foundation | |
url | https://get.foundation |
domain | get.foundation |
datetime | YYYY-MM-DDThh:mm:ssTZD |
date | YYYY-MM-DD |
time | HH:MM:SS |
dateISO | not sure yet |
month_day_year | MM/DD/YYYY |
color | #FFF or #FFFFFF |
You can also use these patterns by setting the input's type to the name of the pattern instead of using the pattern attribute:
<input type="email" required>
<input type="url">
There is a good list of valid HTML5 input types on the Mozilla Developer Network. Try avoiding patterns defined by type that do not match the specification.
You can use the following shortcut for named patterns that aren't valid input types:
<input type="text" pattern="integer">
Custom Named Patterns
By overriding Abide during Foundation initilization, you can define your own custom patterns or override the default patterns to validate against.
$(document)
.foundation({
abide : {
patterns: {
dashes_only: /^[0-9-]*$/,
ip_address: /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/
}
}
});
You can then use these custom patterns like you would the predefined patterns in your markup:
<form class="custom" data-abide>
<label>Serial Number
<input type="text" pattern="dashes_only" required>
</label>
</form>
Equal To
To add a confirmation field, you can define the data-equalto
attribute.
<form data-abide>
<div class="password-field">
<label>Password <small>required</small>
<input type="password" id="password" required pattern="[a-zA-Z]+">
</label>
<small class="error">Your password must match the requirements</small>
</div>
<div class="password-confirmation-field">
<label>Confirm Password <small>required</small>
<input type="password" required pattern="[a-zA-Z]+" data-equalto="password">
</label>
<small class="error">The password did not match</small>
</div>
<button type="submit">Submit</button>
</form>
Error Messages
To display an error message for your invalid form element, include a small
tag with an error
class as a sibling of your input.
<div class="input-wrapper">
<label>Email Address <small>required</small>
<input type="email" required>
</label>
<small class="error">A valid email address is required.</small>
</div>
We have wrapped our input in a div in the example above. This div will receive an error
class when the input is invalid. This class will show our error message and style the label and input accordingly.
Invalid inputs inherit a data-invalid
attribute.
Events
If a submit event is fired, a valid.fndtn.abide
event is triggered when the form is valid and an invalid.fndtn.abide
event is triggered when the form is invalid.
Deprecation Notice
Previous versions of the abide plugin emitted un-namespaced valid
and invalid
events, however, these have been replaced by the namespaced valid.fndtn.abide
and invalid.fndtn.abide
events. The un-namespaced events have been fully deprecated.
You can bind to these events and fire your own callback:
$('#myForm')
.on('invalid.fndtn.abide', function () {
var invalid_fields = $(this).find('[data-invalid]');
console.log(invalid_fields);
})
.on('valid.fndtn.abide', function () {
console.log('valid!');
});
To handle the submit
event yourself, use data-abide="ajax"
instead of data-abide
inside the form
tag.
<form data-abide="ajax" id="myform">
<div class="name-field">
<label>Your name <small>required</small>
<input type="text" name="users_name" required pattern="[a-zA-Z]+">
</label>
<small class="error">Name is required and must be a string.</small>
</div>
<button type="submit">Submit</button>
</form>
$('#myform').on('valid.fndtn.abide', function() {
// Handle the submission of the form
});
Custom Validators
equalTo
is actually an example of a built-in validator. To get an idea of how validators work, check out the implementation of equalTo
:
equalTo: function(el, required, parent) {
var from = document.getElementById(el.getAttribute(this.add_namespace('data-equalto'))).value,
to = el.value,
valid = (from === to);
return valid;
}
Your function will be passed three arguments: el
, required
, and parent
. These are the elements being validated, whether or not it was marked as required, and the parent of the element being validated, respectively.
Your function should return true
if the element is valid, or false
if it is invalid. You can define your custom validators and pass them into abide options when initializing foundation. See the Configuration section for more details on defining custom validators.
Suppose you've defined a custom validator diceRoll
which randomly marks your element as valid or invalid. You would use it like so:
<input type="text" data-abide-validator="diceRoll">
Additionally, if you are using a custom validator and specify an input type or a pattern on the input, Abide will check both when validating the input. The following will check your input value against the built in email pattern as well as your isAllowed custom validator function:
<input type="email" data-abide-validator="isAllowed">
You can also use multiple custom validators if you wish by separating the names of the custom validators with a space. The input, however, must pass ALL validations in order for the input to be considered valid. The example below would only be valid if the the outcome of diceRoll
is true AND the input is within the array of accepted inputs of isAllowed
.
<input type="email" data-abide-validator="diceRoll isAllowed">
Accessibility
For the most part, Abide is accessible on its own. Our JavaScript will add the attribute aria-invalid
to any form fields deemed invalid. However, to properly connect errors to form fields, you'll need to do a little extra work. The error's container should have a unique ID, which our JavaScript will use to bind the error message to its input if there's an error.
<form data-abide>
<div class="name-field">
<label for="input-example">Your name <small>required</small></label>
<input id="input-example" type="text" required pattern="[a-zA-Z]+">
<small class="error">Name is required and must be a string.</small>
</div>
</form>
Adding New Abide Content After Page Load
If you add new content after the page has been loaded, you will need to reinitialize the Foundation JavaScript by running the following:
$(document).foundation('abide', 'reflow');
Reflow will make Foundation check the DOM for any elements and re-apply any listeners to them.
Using the Javascript
foundation.js
are available on your page. You can refer to the Javascript documentation on setting that up.
Just add foundation.abide.js
AFTER the foundation.js
file. Your markup should look something like this:
<body>
...
<script src="js/foundation/foundation.js"></script>
<script src="js/foundation/foundation.abide.js"></script>
<!-- Other JS plugins can be included here -->
<script>
$(document).foundation();
</script>
</body>
Required Foundation Library: foundation.abide.js
Optional Javascript Configuration
$(document).foundation({
abide : {
live_validate : true, // validate the form as you go
validate_on_blur : true, // validate whenever you focus/blur on an input field
focus_on_invalid : true, // automatically bring the focus to an invalid input field
error_labels: true, // labels with a for="inputId" will recieve an `error` class
// the amount of time Abide will take before it validates the form (in ms).
// smaller time will result in faster validation
timeout : 1000,
patterns : {
alpha: /^[a-zA-Z]+$/,
alpha_numeric : /^[a-zA-Z0-9]+$/,
integer: /^[-+]?\d+$/,
number: /^[-+]?[1-9]\d*$/,
// amex, visa, diners
card : /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/,
cvv : /^([0-9]){3,4}$/,
// http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address
email : /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/,
url: /(https?|ftp|file|ssh):\/\/(((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?/,
// abc.de
domain: /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$/,
datetime: /([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])T([0-5][0-9])\:([0-5][0-9])\:([0-5][0-9])(Z|([\-\+]([0-1][0-9])\:00))/,
// YYYY-MM-DD
date: /(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))/,
// HH:MM:SS
time : /(0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]){2}/,
dateISO: /\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/,
// MM/DD/YYYY
month_day_year : /(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d/,
// #FFF or #FFFFFF
color: /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/
},
validators: {
diceRoll: function(el, required, parent) {
var possibilities = [true, false];
return possibilities[Math.round(Math.random())];
},
isAllowed: function(el, required, parent) {
var possibilities = ['a@zurb.com', 'b.zurb.com'];
return possibilities.indexOf(el.val) > -1;
}
}
}
});