A JQuery validation plugin for bootstrap forms.
<input type="email" id="email" required> <input name="emailAgain" data-validation-matches-match="email" data-validation-matches-message= "Must match email address entered above" > <input type="checkbox" name="terms-and-conditions" required data-validation-required-message= "You must agree to the terms and conditions" > <input type="checkbox" name="qualityControl[]" value="fast" minchecked="2" data-validation-minchecked-message="Choose two" maxchecked="2" data-validation-maxchecked-message= "You can't have it all ways" >
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <!-- or use local jquery --> <script src="/js/jqBootstrapValidation.js"></script>
<script> $(function () { $("input,select,textarea").not("[type=submit]").jqBootstrapValidation(); } ); </script>
<form class="form-horizontal"> <div class="control-group"> <label class="control-label">Email address</label> <div class="controls"> <input type="email" /> <p class="help-block"></p> </div> </div> </form>
Attribute | Value | Req? |
---|---|---|
type | ||
data-validation-email-message | (your failure message) |
<form class="form-horizontal"> <div class="control-group"> <label class="control-label">Type something</label> <div class="controls"> <input type="text" name="some_field" required /> <p class="help-block"></p> </div> </div> </form>
Attribute | Value | Req? |
---|---|---|
required | (doesn't need a value) | |
data-validation-required-message | (your failure message) |
<form class="form-horizontal"> <div class="control-group"> <label class="control-label">Type a number</label> <div class="controls"> <input type="number" min="42" name="some_field" /> <p class="help-block">Must be higher than 41</p> </div> </div> </form>
Attribute | Value | Req? |
---|---|---|
min | (minimum number to accept) | |
data-validation-min-message | (your failure message) |
<form class="form-horizontal"> <div class="control-group"> <label class="control-label">Type a number</label> <div class="controls"> <input type="number" max="42" name="some_field" /> <p class="help-block">Must be lower than 43</p> </div> </div> </form>
Attribute | Value | Req? |
---|---|---|
max | (maximum number to accept) | |
data-validation-max-message | (your failure message) |
<form class="form-horizontal" novalidate> <div class="control-group"> <label class="control-label">Type something</label> <div class="controls"> <input type="text" maxlength="10" name="some_field" /> <p class="help-block"></p> </div> </div> </form>
Attribute | Value | Req? |
---|---|---|
maxlength | (maximum number of characters to accept) | |
data-validation-maxlength-message | (your failure message) |
<form class="form-horizontal" novalidate> <div class="control-group"> <label class="control-label">Type something</label> <div class="controls"> <input type="text" minlength="10" name="some_field" /> <p class="help-block"></p> </div> </div> </form>
Attribute | Value | Req? |
---|---|---|
minlength | (minimum number of characters to accept) | |
data-validation-minlength-message | (your failure message) |
<form class="form-horizontal"> <div class="control-group"> <label class="control-label">Type something</label> <div class="controls"> <input type="text" pattern="a.*z" data-validation-pattern-message="Must start with 'a' and end with 'z'" name="some_field" /> <p class="help-block">Must start with 'a' and end with 'z'</p> </div> </div> </form>
Attribute | Value | Req? |
---|---|---|
pattern |
Regex to determine if the input is acceptable Note only expects abc , not /^abc$/ig
|
|
data-validation-pattern-message | (your failure message) |
<form class="form-horizontal"> <div class="control-group"> <label class="control-label">Type something</label> <div class="controls"> <input type="text" name="some_field" /> <p class="help-block"></p> </div> </div> <div class="control-group"> <label class="control-label">Type it again</label> <div class="controls"> <input type="text" data-validation-match-match="some_field" name="some_other_field" /> <p class="help-block"></p> </div> </div> </form>
Attribute | Value | Req? |
---|---|---|
data-validation-match-match | name of form field to match | |
data-validation-match-message | (your failure message) |
<form class="form-horizontal"> <div class="control-group"> <label class="control-label">Select your two favourite colours</label> <div class="controls"> <label class="checkbox"> <input type="checkbox" name="some_field" data-validation-maxchecked-maxchecked="2" data-validation-maxchecked-message="Don't be greedy!" /> Red </label> <label class="checkbox"> <input type="checkbox" name="some_field" /> Orange </label> <label class="checkbox"> <input type="checkbox" name="some_field" /> Yellow </label> <label class="checkbox"> <input type="checkbox" name="some_field" /> Green </label> <label class="checkbox"> <input type="checkbox" name="some_field" /> Blue </label> <label class="checkbox"> <input type="checkbox" name="some_field" /> Indigo </label> <label class="checkbox"> <input type="checkbox" name="some_field" /> Violet </label> <p class="help-block"></p> </div> </div> </form>
Attribute | Value | Req? |
---|---|---|
data-validation-maxchecked-maxchecked | maximum number of options that may be checked | |
data-validation-maxchecked-message | your failure message |
<form class="form-horizontal"> <div class="control-group"> <label class="control-label">Select your two favourite colours</label> <div class="controls"> <label class="checkbox"> <input type="checkbox" name="some_field" data-validation-minchecked-minchecked="2" data-validation-minchecked-message="Choose at least two" /> Red </label> <label class="checkbox"> <input type="checkbox" name="some_field" /> Orange </label> <label class="checkbox"> <input type="checkbox" name="some_field" /> Yellow </label> <label class="checkbox"> <input type="checkbox" name="some_field" /> Green </label> <label class="checkbox"> <input type="checkbox" name="some_field" /> Blue </label> <label class="checkbox"> <input type="checkbox" name="some_field" /> Indigo </label> <label class="checkbox"> <input type="checkbox" name="some_field" /> Violet </label> <p class="help-block"></p> </div> </div> </form>
Attribute | Value | Req? |
---|---|---|
data-validation-minchecked-minchecked | minimum number of options that may be checked | |
data-validation-minchecked-message | your failure message |
<form class="form-horizontal"> <div class="control-group"> <label class="control-label">Select your two favourite colours</label> <div class="controls"> <input type="text" data-validation-regex-regex="a.*z" data-validation-regex-message="Must start with 'a' and end with 'z'" /> <p class="help-block"></p> </div> </div> </form>
Attribute | Value | Req? |
---|---|---|
data-validation-regex-regex | pattern the input must match | |
data-validation-regex-message | your failure message (strongly recommended you make this descriptive) |
<script> function demo_callback_function($el, value, callback) { callback({ value: value, valid: /a.*z/.test(value), message: "Must start with 'a' and end with 'z'" }); } </script> <form class="form-horizontal"> <div class="control-group"> <label class="control-label">Type something</label> <div class="controls"> <input type="text" data-validation-callback-callback="demo_callback_function" /> <p class="help-block"></p> </div> </div> </form>
Attribute | Value | Req? |
---|---|---|
data-validation-callback-callback | name of the callback function | |
data-validation-callback-message |
your failure message Note: You can include this in the callback response in stead, to customise against the user's error |
The callback function will be passed the element (wrapped in jQuery), the field value, and a response function to call when ready.
The response function expects a single variable, a hash containing 'value', 'valid' and optionally 'message'.
The value must be returned, as this is checked against the current value and stale responses are ignored. The 'valid' item in the hash should evaluate to true only if the given value is valid. The message item in the hash, if given, will override the current message on the validator.
Sound a bit complex? Don't worry and take a look at the code tab, its pretty self explanatory.
Warning: While waiting for your function to use the callback, the validator assumes the field is valid. This is to guard against something failing server-side and stopping the user from submitting the form. If your callback takes a long time, the user could be able to submit the form with invalid data without realising.
Note: As github doesn't offer dynamic pages yet, this form is only an example and accepts everything
<form class="form-horizontal"> <div class="control-group"> <label class="control-label">Type something</label> <div class="controls"> <input type="text" name="ajax_input" data-validation-ajax-ajax="/path/to/validator/script" /> <p class="help-block"></p> </div> </div> </form>
<?php echo json_encode( array( "value" => $_REQUEST["value"], "valid" => preg_match("/^[A-Z].*$/", $_REQUEST["value"]), "message" => "Must start with an uppercase letter" ) );
{ "value": "test", "valid": 0, "message": "Must start with an uppercase letter" }
Attribute | Value | Req? |
---|---|---|
data-validation-ajax-ajax | path to the validation page on the server | |
data-validation-ajax-message |
your failure message Note: You can include this in the ajax response in stead, to customise against the user's error |
The ajax call will be passed the field name and the field value.
The response is expected as a JSON hash containing 'value', 'valid' and optionally 'message'.
Value must be returned, as this is checked against the current value so stale responses are ignored. The 'valid' item in the hash should evaluate to true only if the given value is valid. The message item in the hash, if given, will override the current message on the validator.
Sound a bit complex? Don't worry and take a look at the server tab, its pretty self explanatory.
Warning: While waiting for AJAX call, the validator assumes the field is valid. This is to guard against a something failing and stopping the user from submitting the form. If your ajax takes a long time, the user could be able to submit the form with invalid data without realising.
<form class="form-horizontal"> <div class="control-group"> <label class="control-label">Type a number</label> <div class="controls"> <input type="number" /> <p class="help-block"></p> </div> </div> <div class="form-actions"> </form>
Attribute | Value | Req? |
---|---|---|
type | "number" | |
data-validation-number-message | your failure message |
<form class="form-horizontal"> <div class="control-group"> <label class="control-label">Type something</label> <div class="controls"> <input type="text" data-validation-uppercase-regex="([^a-z]*[A-Z]*)*" data-validation-uppercase-message="Must be uppercase" data-validation-containsnumber-regex="([^0-9]*[0-9]+)+" data-validation-containsnumber-message="Needs at least one number" /> <p class="help-block"></p> </div> </div> </form>
Have you noticed how all the validation messages data-attributes look the same?
data-validation-validatorname-message
Validators are attached with names, so you can have multiple of the same validator if you just name them differently.
In the form above, I've added two Regex validators, one requiring uppercase, the other requiring at least one number. Because they are named differently ('uppercase' and 'containsnumber' respectively) they are both applied rather than cancelling eachother out.
You can also use the HTML5 validators multiple times by specifying them in data-attribute format, such as data-validator-myvalidator-maxlength=10
to use the maxlength
HTML5 validator, for example.
Internally, jqBootstrapValidation only uses data attributes. By default, it will also sniff for native HTML5 form validation attributes, as detailed above.
If you decide this isn't what you want, you can restrict jqBootstrapValidation to only data attributes by setting sniffHtml to false when calling it on your form elements.
$(...).jqBootstrapValidation({sniffHtml: false});
By default, jqBootstrapValidtion will prevent forms from submitting if any of their elements fail validation by jqBootstrapValidation.
If you decide this isn't what you want, you can allow submitting of potentially invalid data for validation server-side (or in case you think someone might have a genuine case for exceptional data).
$(...).jqBootstrapValidation({preventSubmit: false});
A javascript callback, used when a user is attempting to submit a form with invalid input.
Parameter | Description |
---|---|
$form | The form element which has the user attempted to submit (wrapped in jQuery) |
event | The submit event (note this may have already been cancelled before you receive it depending on your preventSubmit option). |
errors | An object consisting of the names of fields as keys, and the array of errors as values. |
If you decide you want to react to the invalid submit attempt, you can write a function directly into the jqBootstrapValidation call:
$(/*...*/).jqBootstrapValidation( { submitError: function ($form, event, errors) { /* ... */ } } );Note: The event parameter is a full jQuery event and may be manipulated as normal.
A javascript callback, used when a user is attempting to submit a form with valid input.
Parameter | Description |
---|---|
$form | The form element which has the user attempted to submit (wrapped in jQuery) |
event | The submit event (note this may have already been cancelled before you receive it depending on your preventSubmit option). |
If you decide you want to react to the submit attempt, you can write a function directly into the jqBootstrapValidation call:
$(/*...*/).jqBootstrapValidation( { submitSuccess: function ($form, event) { /* ... */ } } );Note: The event parameter is a full jQuery event and may be manipulated as normal.
If your form is missing help blocks, for example if you don't want an empty element hanging around near 'terms and conditions' check boxes where no explanation would normally be needed, jqBootstrapValidation will add them for you automatically.
If you decide this isn't what you want, for example if you only want the error styling without a warning message, you can stop jqBootstrapValidation from creating extra elements.
$(...).jqBootstrapValidation({autoAdd: {helpBlocks: false}});
jqBootstrapValidation doesn't assume anything about your form, so if you need to ignore some validators in multi-stage forms you can optionally filter them out of the submit event with the filter option.
The this
variable is set to a single element. If you return false, it will be ignored on submit events. For example, the below ignores all elements that are not visible on the page:
$(...).jqBootstrapValidation({ filter: function () { return $(this).is(":visible"); } });
Returns an array of validation errors for a given object.
If no errors are found, returns an empty array.
Note Must be called on a single element via triggerHandler.
To collect all errors for a set of elements, you could use an each loop:
var errorMessages = []; $("...").each(function (i, el) { errorMessages = errorMessages.concat( $(this).triggerHandler("validation.validation") ); });If you just want a list of all error messages for a group of elements, see the "collectErrors" jqBoostrapValidation function.
Returns the internal array of valiators for inspection.
Note Must be called on a single element via triggerHandler.var myValidators = $("...").first().triggerHandler("getValidators.validation");
Removes all jqBootstrapValidation events attached to the given elements, and resets their control-block classes and help-block text to their original values.
$("...").jqBootstrapValidation("destroy");
Collects an object containing arrays of all error messages associated with each invalid element.
var errors = $("...").jqBootstrapValidation("collectErrors");
{ "username": ["...", "..."], "password": ["...", "..."] }
Overrides the internal array, to change the behaviour of default functions, add extra validators, and so on.
WARNING This has the potential to break jqBootstrapValidation. Tread carefully.
You should only use the override function if you are certain you need to, or if you're adding new validators
Because this is a big topic, it has it's own section. See the "Overrides" configuration option.
Returns true if the given collection of elements would show an error when submitted.
if ($("...").jqBootstrapValidation("hasErrors")) { alert("Something is wrong!"); }
Internally, all of jqBootstrapValidation's functions are stored in one big object, which you can override by calling the "override" function with a new object to merge on top of it. Anything you don't set, is left as it was.
Note that as the objects are merged together, you can define your own extra functions, options, etc.
This allows you to duck punch your own solutions, and set up the options in one place rather than on every call to .jqBootstrapValidation()
Question If you override the defaults, will you need to tell anyone else?
You can override the default options by calling the 'override' function and setting the 'options' key with the values you'd use when calling .jqBootstrapValidation()
on a set of elements. As this updates the internal object, all subsequent calls to .jqBootstrapValidation()
will use the new options.
For example, to stop jqBootstrapValidation from preventing an invalid form from being submitted by default:
$.jqBootstrapValidation("override", {options: {preventSubmit: false}});
Allows you to override the methods you can call on jqBootstrapValidation:
Function | Description |
---|---|
init | Used when you call jqBootstrapValidation on a set of elements to set up the validators and events. |
destroy | Removes all hooks jqBootstrapValidation has set on the given set of elements, and any extra elements jqBootstrapValidaiton has added. |
collectErrors | returns an array containing the errors generated by the given collection of elements (or an empty object if none) |
override | this function, used to override other functions |
For example, to prevent anyone from overriding anything else once you're done:
$.jqBootstrapValidation("override", {methods: {override: function () {} }});
Allows you to override the validation methods used when validating a field. You must write the init
and validate
functions.
If your test is too complex for a regex, this is the primary method of adding a custom validator.
For example:
$.jqBootstrapValidation( "override", { validatorTypes: { check_username_ok: // the name of our validator { // the 'name' attribute must match the name used above name: 'check_something_important', init: function ($this, name) { return { like: "green eggs and ham", iAm: "sam i am" }; }, validate: function ($this, value, validator) { console.log(validator.like); // "green eggs and ham" console.log(validator.iAm); // "sam i am" console.log(validator.message); // -- the message displayed for errors -- validator.message = "You can override the message here"; // Perform some checks on the value okValue = value.length > 5 && anExternalCheck(value); // true for valid values, false to display error message return okValue; } } } } );
Attribute | Type | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
init() | function |
Called on each element passed to jqBootstrapValidation that uses the current validator. Returns an object with values that will be copied onto the validator object for future use.
|
||||||||
validate() | function |
Called on each element as it is validated. Returns false if an error is found.
|
||||||||
message | string | Message displayed when the validator fails. |
This section is still being written. The current sections to-do are:
Simply put, I'm in the UK and you probably aren't. English might not even be your first language.
I can't possibly know how you write dates, when even the UK and USA can't agree.
I can't find a nice cross platform way of detecting someone's region preferences easily. If there is enough demand (@ReactiveRaven) I'll add region support, but for now you may be better finding a non-restrictive regex for your local format.
The best place to reach me is on twitter @ReactiveRaven. If you don't have a twitter account, you could email me in stead. It turns out I'm terrible at answering emails though, so please don't be surprised if I'm slow to respond. Sorry!
If you think you've found a bug, please do file an issue on github or better yet, fork and send a pull request.