npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@stormid/validate

v1.0.0-alpha.34

Published

Client-side form validation

Downloads

811

Readme

Validate

Client-side form validation library to support .NET validation using data-val attributes as a drop-in replacement for jQuery validate, and HTML5 attribute-based constraint validation.


Contents

Usage

Install the package

npm i -S @stormid/validate

Import the module

import validate from '@stormid/validate';

Initialise the module via selector string

const [ validator ] = validate('form:not([novalidate])');

Initialise with a DOM element

const element = document.querySelector('form:not([novalidate])');
const [ validator ] = validate(element);

Initialise with a Node list

const elements = document.querySelectorAll('form:not([novalidate])');
const [ validator ] = validate(elements);

Initialise with an Array of elements

const elements = [].slice.call(document.querySelectorAll('form:not([novalidate])'));
const [ validator ] = validate(elements);

Validators

This library supports HTML5 attribute constraints and the data-val attributes generated by .Net Core model validation, .Net MVC DataAnnotation, or .Net Fluent validation libraries.

Multiple validators can be used on a single field. Custom validators can be added via the addMethod API.


Required

The field must have a value. Checkboxes are treated as non-nullable in required validation.

HTML5

<input name="field" id="field" required>

Data attributes

<input name="field" id="field" data-val="true" data-val-required="'field' is required">

Email

Value is matched against the regular expression

/^[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])?)*$/

which is equivalent to the browser algorithm used in the constraint validation API for type="email", and is intentionally loose due to known issues related to international domain names and the validation of e-mail addresses in HTML. Stricter or more specific validation rules can be specified with a pattern attribute (or data-val-regex).

HTML5

<input type="email" name="field" id="field">

Data attributes

<input name="field" id="field" data-val="true" data-val-email="'field' must be a valid email address">

Url

The value is matched against this regular expresion by Diego Perini

/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i

Stricter or more specific validation rules can be specified with a pattern attribute (or data-val-regex).

HTML5

<input type="url" name="field" id="field">

Data attributes

<input name="field" id="field" data-val="true" data-val-url="'field' must be a valid url">

Pattern/Regex

Value matches the supplied pattern or regular expression

HTML5

<input name="field" id="field" pattern="^http(s)?">

Data attributes

<input name="field" id="field" data-val="true" data-val-regex="'field' must start with http or https" data-val-regex-pattern="^http(s)?">

Digits

Value must contain only characters in the range 0-9

Data attributes

<input name="field" id="field" data-val="true" data-val-digits="'field' must be a number">

Number

Value is matched against the regular expresion

/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/;

Allowing positive and negative numbers, decimals, and comma separated thousands.

HTML5

<input type="number" name="field" id="field">

Data attributes

<input name="field" id="field" data-val="true" data-val-number="'field' must be a number">

Min

Value is a Number greater or equal to min

HTML5

<input type="number" name="field" id="field" min="0">

Data attributes

<input type="number" name="field" id="field" data-val="true" data-val-min="'field' must be >= 0" data-val-min-min="0">

Max

Value is a Number less than or equal to max

HTML5

<input type="number" name="field" id="field" max="100">

Data attributes

<input type="number" name="field" id="field" data-val="true" data-val-max="'field' must be <= 100" data-val-max-max="100">

Range

Value is a Number within the specified min and max

Data attributes

<input type="number" name="field" id="field" data-val="true" data-val-range="'field' must be between 0 and 100" data-val-range-min="0" data-val-range-max="100">

Length

Value is a String with a length greater than or equal to min and/or a length less than or equal to max

Data attributes

<input name="field" id="field" data-val="true" data-val-length="'field' length must be between 2 and 4" data-val-length-min="2" data-val-length-max="4">

Stringlength

Value is a String with a length less than or equal to max. Equivalent to the length/max validator, generated by .Net stringlength data notation.

Data attributes

<input name="field" id="field" data-val="true" data-val-stringlength="'field' length must be less than 4" data-val-stringlength-max="4">

Maxlength

Value is a String with a length less than or equal to max. Equivalent to the length/max validator, generated by .Net maxlength data notation.

.HTML5

<input name="field" id="field" maxlength="4">

Data attributes

<input name="field" id="field" data-val="true" data-val-maxlength="'field' length must be less than 4" data-val-maxlength-max="4">

Minlength

Value is a String with a length greater than or equal to min. Equivalent to the length/min validator, generated by .Net minlength data notation.

.HTML5

<input name="field" id="field" minlength="2">

Data attributes

<input name="field" id="field" data-val="true" data-val-minlength="'field' length must be greater than 2" data-val-minlength-min="2">

DateISO

Value is a string in a format matching the date ISO standard, (YYYY-MM-DD), matching the regular expression

/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/

Data attributes

<input name="field" id="field" data-val="true" data-val-dateISO="'field' must in the format YYYY-MM-DD">

Equalto

Value must match the value of another field (or multiple fields). The data-val-equalto-other attribute is the name of another field, or a comma-separated list of names of multiple fields.

Data attributes

<input name="password" id="password">
...
<input name="passwordConfirmation" id="passwordConfirmation" data-val="true" data-val-equalto="'password confirmation' must match 'password'" data-val-equalto-other="password">

Remote

Value is validated against via XHR against a remote resource. The resouce is defined by the data-val-remote-url attribute.

Defaults to a POST request, data-val-remote-type can be set to make GET requests.

The values of additional fields can be sent in the request by specifying a data-val-remote-additionalfields attribute, a comma separated list of field ids to be included.

Data attributes

<input name="field" id="field" data-val="true" data-val-remote="'field' must pass remote validation" data-val-remote-url="/api/validate">

Errors

Error message container

The element to contain server-side error messages generated by .Net fluent and unobtrustive validation libraries is recycled by this library, it can also be manually added to HTML when you need more control over the position and markup of the error message container. The data-valmsg-for provides the association between error message and field/field group name, the id is used by the library to associate the error with the input using aria-describedby.

<span id="field-error-message" class="field-validation-valid" data-valmsg-for="field" />

If this element is not present a span is appended to the label for the field with the className .error-message.

Error messages

.Net error messages are extracted from data-val-[validator-type] data attributes, and apply to both HTML5 and .Net validators.

Fields without data-val error messages will show the default messages for the failed validator (see options below).

Including values in error messages

To include the user input value in your error message, place a token "{{value}}" within the message string and the script will replace it at the time of validation. e.g. "{{value}} is not a valid email address" will become "test@test is not a valid email address".

If a validation group contains more than one field, the values of these will be returned as a comma seperated list within the message. For example: "{{value}} are not valid inputs" becomes "test1, test2 are not valid inputs".

Options

{
    preSubmitHook: false, //function, called on validation pass, before submit
    submit: form.submit, // function, to support async form submissions, pass your own submit function
    messages: { //default HTML5 error messages
        required() { return 'This field is required'; } ,
        email() { return 'Please enter a valid email address'; },
        pattern() { return 'The value must match the pattern'; },
        url(){ return 'Please enter a valid URL'; },
        number() { return 'Please enter a valid number'; },
        digits() { return 'Please enter only digits'; },
        maxlength(props) { return `Please enter no more than ${props.max} characters`; },
        minlength(props) { return `Please enter at least ${props.min} characters`; },
        max(props){ return `Please enter a value less than or equal to ${props.max}`; },
        min(props){ return `Please enter a value greater than or equal to ${props.min}`}
    }
}

API

validate() returns an array of instances. Each instance exposes the interface

{
    validate
    addMethod
    validateGroup
    addGroup
    removeGroup
}

addMethod

Add a custom validation method to a group:

const [ validator ] = validate('.my-form');

validator.addMethod(
    'MyFieldName', //input/input group name/or validation group name if passing an array of fields
    (value, fields) => { //validation method
        //value is the value of the whole group of fields (grouped under the name attribute)
        return value === 'test'; //must return boolean
    },
    'Value must equal "test"', //error message on validation failure
    fields // an optional array of inputs, if this isn't present the input/groupName is used as a name (or data-group) attribute selector
);

validate

Manually trigger validation on the whole form, returns a promise:

const [ validator ] = validate('.my-form');

await validator.validate();

addGroup

Add a field or field group to the validator:

const [ validator ] = validate('.my-form');
const fieldsArray = Array.from(document.querySelector('.new-fields'))

//add by passing an array of fields
//if these fields span multiple groups they will be collected into the correct validation groups internally by the validator
validator.addGroup(fieldsArray);

validateGroup

Immediately validates an individual group within the form:

const [ validator ] = validate('.my-form');
const validator.validateGroup('myInput');

//pass in the name or data-val-group value that corresponds to the group you're looking to validate
//returns a promise which resolves with the validity state of the group (true if valid, false if invalid)

removeGroup

Remove a validation group from the validator:

const [ validator ] = validate('.my-form');
const fieldsArray = Array.from(document.querySelectorAll([name=new-fields]))

//add by passing an array of fields
validator.addGroup(fieldsArray);

//remove by passing the name of a group
validator.removeGroup('new-fields');

Plugins

Plugins are a set of pre-built custom validators that are included in the package but not in the default build. They can be imported and used in addMethod you would your own custom validation method.

isValidDate

Validate three separate day/month/year fields (similar to the govuk design system date component) as a single valid date.

The minimum accepted year value in the isValidDate plugin is 1000. To set a different (more recent) minimum value consider using the min validator on the year input.

isFutureDate

Validate three separate day/month/year fields (similar to the govuk design system date component) as a single date in the future.

isPastDate

Validate three separate day/month/year fields (similar to the govuk design system date component) as a single date in the past- today's date is valid.

HTML

<fieldset>
    <legend>
        <span>Date</span>
        <span data-valmsg-for="date" id="date-error-message"></span>
        <span data-valmsg-for="dateDay" id="date-Day-error-message"></span>
        <span data-valmsg-for="dateMonth" id="date-Month-error-message"></span>
        <span data-valmsg-for="dateYear" id="date-Year-error-message"></span>
    </legend>
    <div class="flex">
        <input id="dateDay" name="dateDay" inputmode="numeric" data-val="true" data-val-required="Enter a day" aria-required="true"/>
        <input id="dateMonth" name="dateMonth" inputmode="numeric" data-val="true" data-val-required="Enter a month" aria-required="true"/>
        <input id="dateYear" name="dateYear" inputmode="numeric" data-val="true" data-val-required="Enter a year" aria-required="true" />
    </div>
</fieldset>

JS

import validate from '@stormid/validate';
import { isValidDate } from '@stormid/validate/src/lib/plugins/methods/date';

const [ validator ] = validate('.my-form');
validator.addMethod(
  'date', //name of custom validation group
  isValidDate, // date validation method imported from the library 
  'Enter a valid date', // error message
  [ document.getElementById('dateDay'), document.getElementById('dateMonth'), document.getElementById('dateYear') ] //date fields array [day, month, year]
);

Tests

npm t

License

MIT