---
title: f-validate – Form Validation Module
section-title: JS Components
docs: true

navgroup: styleguide
navsub: js-components
navactive: validation
---


The f-validation module is used to add client-side validation to a form.

The module aims to use the default HTML5 form validation attrbutes wherever possible and extend this with it's own rules for more specific validation checks.

For example, if an input within a form passed to `f-validate` has a type of `email` set, the module will apply the email validation rule to that field.

<a name="usage"></a><h2 class="sg-sectionHeading">Usage</h2>

To setup `f-validate`, you first need to install the module using Yarn or NPM.

```bash
yarn add @justeat/f-validate
```

Then within your JavaScript, import the module:

```javascript
import Validate from '@justeat/f-validate';
```

Once you have imported the module, you can then attach `f-validate` to a form.  To do this, you can either pass in the name of your form or the form element itself, such that:

```javascript
// 1. Pass in the name of the form to be validated
new FormValidation('formName');


// 2. Pass in the form element to be validated
const myForm = document.querySelector('.myForm');
new FormValidation(myForm);
```

Once you have done this, `f-validate` will automatically validate the form based on the HTML5 form attributes set on each field (such as `required`) or by checking whether a field has the specified rule data-attribute set on it.  For more information on how to specify rules, see the [Validation Rules section](#rules) below.

---

<a name="rules"></a><h2 class="sg-sectionHeading">Validation Rules</h2>

`f-validate` aims to use the default HTML5 form validation attrbutes wherever possible.  For example, if an input has a type of `email`, it will apply the email validation test to it.

The following rules are currently available within the validation module to apply to fields.

- [Required](#rules-required)
- [Email](#rules-email)
- [Minlength](#rules-minlength)
- [Maxlength](#rules-maxlength)
- [Pattern](#rules-pattern)
- [Matches](#rules-matches)
- [Date In Future](#rules-dateinfuture)
- [Conditional Required](#rules-conditionalrequired)
- [Custom](#rules-custom)




<a name="rules-required"></a><h3 class="sg-sectionHeading">Required</h3>

**Valid field types** = `input` | `select` | `textarea` | `radio` | `checkbox`
**Default Error Message** = 'This field is required.'
---

This rule checks that a value is present for the field being validated.

To validate a field with this rule, either set the `required` HTML5 attribute or add the `data-val-required` attribute to the field:

```markup
// via required attribute
<input type="text" required />

// via data-val-required attribute
<input type="text" data-val-required />
```

When set on an `input`, `select` or `textarea` field, a value must be present for this rule to pass validation.

For fields of type `checkbox`, this rule checks that the field has been `checked` and for fields of type `radio`, this rule will validate as true as long as one radio button with the same `name` attribute has been selected.

{{#>demo-block }}
<div class="g g--alignCenter">
    <div class="g-col g-span6">
        <form name="test-form">
            <label>Name:
                <input type="text" required>
            </label>
            <button type="submit" class="o-btn o-btn--primary o-btn--block">Submit</button>
        </form>
    </div>
</div>
{{/demo-block }}




<a name="rules-email"></a><h3 class="sg-sectionHeading">Email</h3>

**Valid field type** = `input`
**Default Error Message** = 'This field must contain a valid email address.'
---

This rule checks that the value of the field being validated is a valid email address.

To validate a field with this rule, set its type such that `type="email"`.

```markup
<input type="email" />
```

This rule uses the following regular expression to validate email addresses:

```bash
/^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
```

{{#>demo-block }}
<div class="g g--alignCenter">
    <div class="g-col g-span6">
        <form name="test-form">
            <label>Email:
                <input type="email">
            </label>
            <button type="submit" class="o-btn o-btn--primary o-btn--block">Submit</button>
        </form>
    </div>
</div>
{{/demo-block }}




<a name="rules-minlength"></a><h3 class="sg-sectionHeading">Minlength</h3>

**Valid field types** = `input` | `textarea`
**Default Error Message** = 'This field must be at least {0} characters in length.'
---

This rule checks that the value of the field is of a specified minimum length.  Note that it doesn't check if a value has been entered (like the `required` rule), simply that if a value has been entered by the user, then it should be at least `x` characters in length.

It can be applied to `input` and `textarea` fields.

To validate a field with this rule, eiher set the `minlength` attribute or add the `data-val-minlength` attribute to the field:

```markup
// via minlength attribute
<input type="text" minlength="5" />

// via data-val-minlength attribute
<input type="text" data-val-minlength="5" />
```

{{#>demo-block }}
<div class="g g--alignCenter">
    <div class="g-col g-span6">
        <form name="test-form">
            <label>Name (minimum 5 characters):
                <input type="text" minlength="5">
            </label>
            <button type="submit" class="o-btn o-btn--primary o-btn--block">Submit</button>
        </form>
    </div>
</div>
{{/demo-block }}




<a name="rules-maxlength"></a><h3 class="sg-sectionHeading">Maxlength</h3>

**Valid field types** = `input` | `textarea`
**Default Error Message** = 'This field must not exceed {0} characters in length.',
---

This rule checks that the value of the field is no greater than the specified maximum length.

To validate a field with this rule, eiher set the `maxlength` attribute or add the `data-val-minlength` attribute to the field:

```markup
// via maxlength attribute
<input type="text" maxlength="20" />

// via data-val-maxlength attribute
<input type="text" data-val-maxlength="20" />
```

Note that when using the `maxlength` attribute, most modern browsers will stop the user entering more than the number of characters specified.

{{#>demo-block }}
<div class="g g--alignCenter">
    <div class="g-col g-span6">
        <form name="test-form">
            <label>Name (maximum 5 characters):
                <input type="text" maxlength="5">
            </label>
            <button type="submit" class="o-btn o-btn--primary o-btn--block">Submit</button>
        </form>
    </div>
</div>
{{/demo-block }}




<a name="rules-pattern"></a><h3 class="sg-sectionHeading">Pattern</h3>

**Valid field types** = `input` | `textarea`
**Default Error Message** = 'This field contains a value that isn’t accepted.'
---

This rule checks that the value of the field matches the regular expression specified.  The pattern must match the entire value and not just some subset.

To validate a field with this rule, eiher set the `pattern` attribute or add the `data-val-regex` attribute to the field:

```markup
// via pattern attribute
<input type="text" pattern="[a-z]{1,6}" />

// via data-val-maxlength attribute
<input type="text" data-val-regex="[a-z]{1,6}" />
```

It's considered best practice to set the title attribute when validating with this rule to describe the pattern to help the user.

{{#>demo-block }}
<div class="g g--alignCenter">
    <div class="g-col g-span6">
        <form name="test-form">
            <label>Pattern (Valid pattern = a string of 1-6 letters):
                <input type="text" pattern="[a-z]{1,6}">
            </label>
            <button type="submit" class="o-btn o-btn--primary o-btn--block">Submit</button>
        </form>
    </div>
</div>
{{/demo-block }}




<a name="rules-matches"></a><h3 class="sg-sectionHeading">Matches</h3>

**Valid field type** = `input`
**Default Error Message** = 'This field does not match the {0} field.'
---

This rule checks that the value of the field being validated matches the value of a separate specified field.  To be valid it must match the entire value and not just some subset.

To validate a field with this rule, set the `data-val-equalto` attribute to the field:

```markup
// via data-val-maxlength attribute
<input type="text" data-val-equalto="matchedField" />

// note that a field with the name passed should exist, or the rule will always fail
<input type="text" name="matchedField" />
```

{{#>demo-block }}
<div class="g g--alignCenter">
    <div class="g-col g-span6">
        <form name="test-form">
            <ul class="u-unstyled">
                <li>
                    <label>First field
                        <input type="text" required data-val-equalto="fieldTwo">
                    </label>
                </li>
                <li>
                    <label>Second field
                        <input type="text" name="fieldTwo">
                    </label>
                </li>
            </ul>
            <button type="submit" class="o-btn o-btn--primary o-btn--block">Submit</button>
        </form>
    </div>
</div>
{{/demo-block }}




<a name="rules-dateInFuture"></a><h3 class="sg-sectionHeading">Date In Future</h3>

**Valid field type** = `select`
**Default Error Message** = 'This date must be in the future.'
---

This rule is for validating dates entered by a collection of `select` fields.  When applied to a group of fields, it returns true if the date entered in these fields is in the future.

Currently, this rule only validates dates specified with a month and year and has not yet been extended to test for day.

To validate a group with this rule, set the `data-val-group` and `data-val-dateinfuture` attributes on the container wrapping the `select` fields.

Then apply the `data-val-dateinfuture-type="month"` and `data-val-dateinfuture-type="year" attributes to each `select` field, such that:

```markup
// Apply `data-val-dateinfuture` attribute to the outer container
<div data-val-group data-val-dateinfuture>
    // Apply `data-val-dateinfuture-type` attributes to the relevant `select` fields
    <select data-val-dateinfuture-type="year">
        <option value="" ></option>
        <option value="2018"></option>
    </select>
    <select data-val-dateinfuture-type="month">
        <option value="" ></option>
        <option value="01"></option>
    </select>
</div>
```

{{#>demo-block }}
<div class="g">
    <div class="g-col g-span4">
        <form name="test-form">
            <div data-val-group data-val-dateinfuture>
                <select data-val-dateinfuture-type="year">
                    <option value="" ></option>
                    <option value="2017">2017</option>
                    <option value="2018">2018</option>
                    <option value="2019">2019</option>
                    <option value="2020">2020</option>
                </select>
                <select data-val-dateinfuture-type="month">
                    <option value="" ></option>
                    <option value="01">01</option>
                    <option value="02">02</option>
                    <option value="03">03</option>
                    <option value="04">04</option>
                    <option value="05">05</option>
                    <option value="06">06</option>
                    <option value="07">07</option>
                    <option value="08">08</option>
                    <option value="09">09</option>
                    <option value="10">10</option>
                    <option value="11">11</option>
                    <option value="12">12</option>
                </select>
            </div>
            <button type="submit" class="o-btn o-btn--primary o-btn--block">Submit</button>
        </form>
    </div>
</div>
{{/demo-block }}




<a name="rules-conditionalRequired"></a><h3 class="sg-sectionHeading">Conditional Required</h3>

**Valid field type** = `input`
**Default Error Message** = 'This field is required.'
---

This validation rule checks that if a specified checkbox is not checked, then it is required that a value must be entered in the field with this validation check.

This also means that if the specified checkbox is checked, then the field is not required and the form will return valid when the field is empty.

To validate a field with this rule, set the `data-val-conditionalrequired` attribute on the field to be validated, passing in the name of the checkbox to validate against:

```markup
// via `data-val-conditionalrequired` attribute
<input type="text" data-val-conditionalrequired="nameOfcheckedInput" />
// the checkbox to test against
<input type="checkbox" name="nameOfcheckedInput" />
```

{{#>demo-block }}
<div class="g g--alignCenter">
    <div class="g-col g-span6">
        <form name="test-form">
            <ul class="u-unstyled">
                <li>
                    <label>Name:
                        <input type="text" data-val-conditionalrequired="nameOfcheckedInput" />
                    </label>
                </li>
                <li>
                    <label>If this isn't checked, then the name field is required:
                        <input type="checkbox" name="nameOfcheckedInput" />
                    </label>
                </li>
            </ul>
            <button type="submit" class="o-btn o-btn--primary o-btn--block">Submit</button>
        </form>
    </div>
</div>
{{/demo-block }}




<a name="rules-custom"></a><h3 class="sg-sectionHeading">Custom</h3>

**Valid field type** = All
**Default Error Message** = 'Custom validation failed.'
---

This validation rule allows the addition of a custom validation check to be added to the field.

To validate a field with a custom rule, you need to first set the `data-val-custom` attribute with the name of the function you want to call when the form is submitted.

You should then ensure that a `data-val-custom-error` attribute has been set with your custom error message.

```markup
// Apply data attributes to your field
<form name="myForm">
    <input data-val-custom="customRule" data-val-custom-error="The value entered does not match 'passTest'" />
</form>
```

Then in the JavaScript, after you have initialised `f-validate` on your form, you should pass in the custom validation function, using the `addCustomValidation` method, such that:

```javascript
const validateForm = new Validate('myForm');

// Pass in a custom validation function
// This function will receive the field being validated
validateForm.addCustomValidation('customRule', field => {
    if (field.value === 'passTest') {
        return true;
    }
    return false;
});
```


{{#>demo-block }}
<div class="g g--alignCenter">
    <div class="g-col g-span6">
        <form name="test-form">
            <input data-val-custom="customRule" data-custom-error="The value entered does not match 'passTest'" />
            <button type="submit" class="o-btn o-btn--primary o-btn--block">Submit</button>
        </form>
    </div>
</div>
{{/demo-block }}



<h2 class="sg-sectionHeading">Rule table</h2>

<table class="js-options">
    <tr>
        <th>Rule</th>
        <th>Fields</th>
        <th>Hooks</th>
    </tr>
    <tr>
        <td><code>Required</code></td>
        <td><p><code>input</code></p><p><code>select</code></p><p><code>textarea</code></p><p><code>radio</code></p><p><code>checkbox</code></p></td>
        <td><code>required</code> | <code>data-val-required</code></td>
    </tr>
    <tr>
        <td><code>Email</code></td>
        <td><p><code>input</code></p></td>
        <td><code>type="email"</code></td>
    </tr>
    <tr>
        <td><code>Minlength</code></td>
        <td><p><code>input</code> | <code>textarea</code></p></td>
        <td><code>minlength</code> | <code>data-val-minlength</code></td>
    </tr>
    <tr>
        <td><code>Maxlength</code></td>
        <td><p><code>input</code> | <code>textarea</code></p></td>
        <td><code>maxlength</code> | <code>data-val-maxlength</code></td>
    </tr>
    <tr>
        <td><code>Pattern</code></td>
        <td><p><code>input</code> | <code>textarea</code></p></td>
        <td><code>pattern</code> | <code>data-val-regex</code></td>
    </tr>
    <tr>
        <td><code>Matches</code></td>
        <td><p><code>input</code> | <code>textarea</code></p></td>
        <td><code>data-val-equalto</code></td>
    </tr>
    <tr>
        <td><code>Date In Future</code></td>
        <td><p><code>select</code></p></td>
        <td>Multiple (see example)</td>
    </tr>
    <tr>
        <td><code>Conditional Required</code></td>
        <td><p><code>input</code></p></td>
        <td><code>data-val-conditionalRequired</code></td>
    </tr>
</table>


<a name="messages"></a><h2 class="sg-sectionHeading">Custom Error Messages</h2>

It's common to want to customise the messages displayed when certain fields aren't valid.  To do this, you can define a data attribute specific to the validation rule you want the message to apply for, such that `data-val-{validation-rule}-error`.

For example:

```markup
// To replace the default error message when using the `required` validation rule
// set `data-val-required-error` to the message you would like to display
<input type="text" required data-val-required-error="This is my new required error message" />

// Similarly for other validation rules
// email:
<input type="email" data-val-email-error="This is my new email error message" />

// minlength:
<input type="text" minlength="5" data-val-minlength-error="This is my new minlength error message" />

// maxlength:
<input type="text" maxlength="5" data-val-maxlength-error="This is my new maxlength error message" />

// pattern:
<input type="text" pattern="[a-z]{1,6}" data-val-pattern-error="This is my new pattern error message" />

// matches:
<input type="text" matches="fieldToMatch" data-val-matches-error="This is my new matches error message" />

// conditionalrequired:
<input type="text" data-val-conditionalrequired="nameOfcheckedInput" data-val-conditionalrequired-error="This is my new matches error message" />

// for dateInFuture, apply the `data-val-dateinfuture` to the outer container
<div data-val-group data-val-dateinfuture data-val-dateinfuture-error="This is my new dateInFuture error message">
```

{{#>demo-block }}
<div class="g g--alignCenter">
    <div class="g-col g-span6">
        <form name="test-form">
            <ul class="u-unstyled">
                <li>
                    <label>Name:
                        <input type="text" data-val-required data-val-required-error="This is a custom required error message" />
                    </label>
                </li>
            </ul>
            <button type="submit" class="o-btn o-btn--primary o-btn--block">Submit</button>
        </form>
    </div>
</div>
{{/demo-block }}


<a name="options"></a><h2 class="sg-sectionHeading">Options</h2>

`f-validate` has a number of options that allow you to customise its functionality.

The properties or attributes that can be defined are as follows:

<table class="js-options">
    <tr>
        <th>Setting</th>
        <th>Type</th>
        <th>Values</th>
        <th>Description</th>
    </tr>
    <tr>
        <td><code>errorClass</code></td>
        <td>string</td>
        <td><code>String</code> | <code>has-error</code>(default)</td>
        <td>Defines the class applied to each field when they fail validation.  By default, the class added is `has-error`.</td>
    </tr>
    <tr>
        <td><code>successClass</code></td>
        <td>string</td>
        <td><code>String</code> | <code>has-success</code>(default)</td>
        <td>Defines the class applied to each field when they pass validation.  By default, the class added is `has-success`.</td>
    </tr>
    <tr>
        <td><code>groupErrorPlacement</code></td>
        <td>string</td>
        <td><code>bottom</code> | <code>top</code> | <code>Selector</code></td>
        <td>
            <p>When set, error messages will be grouped together rather than placed adjacent to each field.</p>
            <p>If this value is set to `bottom`, then the error messages will be grouped at the bottom of the form.</p>
            <p>If this value is set to `top`, then the error messages will be grouped at the top of the form.</p>
            <p>If this value is set as a selector such as `.myClassName` or `[type="submit"]`, then the error messages will be grouped above the element matched in that selector.  If this element isn't found, then it will group error messages as if the `top` value had been specified.</p>
        </td>
    </tr>
    <tr>
        <td><code>enableHTML5Validation</code></td>
        <td>boolean</td>
        <td><code>true</code> | <code>false</code> (default)</td>
        <td>
            <p>Sets whether the `novalidate` attribute is added to the form being validated.</p>
            <p>By default, `novalidate` is added to a form that is being validated to supress native HTML5 validation.  By setting this option to `true` this attribute is not set and native HTML5 validation will not be supressed.</p>
        </td>
    </tr>
    <!-- <tr>
        <td><code>focus</code></td>
        <td>boolean</td>
        <td><code>true</code> | <code>false</code> (default)</td>
        <td>Specifies if you would like the first field found to be invalid to be focussed after the form has been validated.  (Note this is an planned feature and has not been fully implemented)</td>
    </tr> -->
</table>



<a name="messages-grouped"></a><h2 class="sg-sectionHeading">Grouped Error Messages</h2>

Sometimes, rather than display one error per field, you may want to display all of the forms validation messages together as a group.

To do this, you will need to specify the `groupErrorPlacement` option when you initialise `f-validate`.

```javascript
new FormValidation(nameOfForm, {
    groupErrorPlacement: 'bottom'
});
```

To see all possible options that `groupErrorPlacement` accepts, check the [options](#options) section of the documentation.

{{#>demo-block }}
<div class="g g--alignCenter">
    <div class="g-col g-span6">
        <form name="test-form-group">
            <ul class="u-unstyled">
                <li>
                    <label>Name:
                        <input type="text" data-val-required data-val-required-error="This is a custom required error message" />
                    </label>
                </li>
                <li>
                    <label>Email:
                        <input type="email" data-val-email-error="This is a custom email error message" />
                    </label>
                </li>
                <li>
                    <label>Postcode:
                        <input type="text" pattern="[a-z]{0-6}" data-val-pattern-error="This is a custom pattern error message" />
                    </label>
                </li>
            </ul>
            <button type="submit" class="o-btn o-btn--primary o-btn--block">Submit</button>
        </form>
    </div>
</div>
{{/demo-block }}



<a name="multiple-rules"></a><h2 class="sg-sectionHeading">Applying Multiple Rules</h2>

To apply multiple rules to the same field, you simply need to add multiple attributes to define the rules you want to validate.

```markup
// To make a field validate as required and of type email
<input type="email" required />

// To make a field validate as minlength and maxlength
<input type="text"
    data-val-minlength
    data-val-maxlength
    data-val-minlength-error="Custom error minlength"
    data-val-maxlength-error="Custom error maxlength" />
```

{{#>demo-block }}
<div class="g g--alignCenter">
    <div class="g-col g-span6">
        <form name="test-form">
            <ul class="u-unstyled">
                <li>
                    <label>Name:
                        <input type="text"
                            data-val-minlength="2"
                            data-val-maxlength="5"
                            data-val-minlength-error="Name should be at least 2 characters long"
                            data-val-maxlength-error="Name should be a maximum of 5 characters long" />
                    </label>
                </li>
                <li>
                    <label>Email:
                        <input type="email" required />
                    </label>
                </li>
            </ul>
            <button type="submit" class="o-btn o-btn--primary o-btn--block">Submit</button>
        </form>
    </div>
</div>
{{/demo-block }}
