• Stars
    star
    8,850
  • Rank 4,110 (Top 0.09 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created almost 10 years ago
  • Updated 10 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

validate form asynchronous

async-validator

NPM version build status Test coverage node version npm download npm bundle size (minified + gzip)

Validate form asynchronous. A variation of https://github.com/freeformsystems/async-validate

Install

npm i async-validator

Usage

Basic usage involves defining a descriptor, assigning it to a schema and passing the object to be validated and a callback function to the validate method of the schema:

import Schema from 'async-validator';
const descriptor = {
  name: {
    type: 'string',
    required: true,
    validator: (rule, value) => value === 'muji',
  },
  age: {
    type: 'number',
    asyncValidator: (rule, value) => {
      return new Promise((resolve, reject) => {
        if (value < 18) {
          reject('too young');  // reject with error message
        } else {
          resolve();
        }
      });
    },
  },
};
const validator = new Schema(descriptor);
validator.validate({ name: 'muji' }, (errors, fields) => {
  if (errors) {
    // validation failed, errors is an array of all errors
    // fields is an object keyed by field name with an array of
    // errors per field
    return handleErrors(errors, fields);
  }
  // validation passed
});

// PROMISE USAGE
validator.validate({ name: 'muji', age: 16 }).then(() => {
  // validation passed or without error message
}).catch(({ errors, fields }) => {
  return handleErrors(errors, fields);
});

API

Validate

function(source, [options], callback): Promise
  • source: The object to validate (required).
  • options: An object describing processing options for the validation (optional).
  • callback: A callback function to invoke when validation completes (optional).

The method will return a Promise object like:

  • then(),validation passed
  • catch({ errors, fields }),validation failed, errors is an array of all errors, fields is an object keyed by field name with an array of errors per field

Options

  • suppressWarning: Boolean, whether to suppress internal warning about invalid value.

  • first: Boolean, Invoke callback when the first validation rule generates an error, no more validation rules are processed. If your validation involves multiple asynchronous calls (for example, database queries) and you only need the first error use this option.

  • firstFields: Boolean|String[], Invoke callback when the first validation rule of the specified field generates an error, no more validation rules of the same field are processed. true means all fields.

Rules

Rules may be functions that perform validation.

function(rule, value, callback, source, options)
  • rule: The validation rule in the source descriptor that corresponds to the field name being validated. It is always assigned a field property with the name of the field being validated.
  • value: The value of the source object property being validated.
  • callback: A callback function to invoke once validation is complete. It expects to be passed an array of Error instances to indicate validation failure. If the check is synchronous, you can directly return a false or Error or Error Array.
  • source: The source object that was passed to the validate method.
  • options: Additional options.
  • options.messages: The object containing validation error messages, will be deep merged with defaultMessages.

The options passed to validate or asyncValidate are passed on to the validation functions so that you may reference transient data (such as model references) in validation functions. However, some option names are reserved; if you use these properties of the options object they are overwritten. The reserved properties are messages, exception and error.

import Schema from 'async-validator';
const descriptor = {
  name(rule, value, callback, source, options) {
    const errors = [];
    if (!/^[a-z0-9]+$/.test(value)) {
      errors.push(new Error(
        util.format('%s must be lowercase alphanumeric characters', rule.field),
      ));
    }
    return errors;
  },
};
const validator = new Schema(descriptor);
validator.validate({ name: 'Firstname' }, (errors, fields) => {
  if (errors) {
    return handleErrors(errors, fields);
  }
  // validation passed
});

It is often useful to test against multiple validation rules for a single field, to do so make the rule an array of objects, for example:

const descriptor = {
  email: [
    { type: 'string', required: true, pattern: Schema.pattern.email },
    { 
      validator(rule, value, callback, source, options) {
        const errors = [];
        // test if email address already exists in a database
        // and add a validation error to the errors array if it does
        return errors;
      },
    },
  ],
};

Type

Indicates the type of validator to use. Recognised type values are:

  • string: Must be of type string. This is the default type.
  • number: Must be of type number.
  • boolean: Must be of type boolean.
  • method: Must be of type function.
  • regexp: Must be an instance of RegExp or a string that does not generate an exception when creating a new RegExp.
  • integer: Must be of type number and an integer.
  • float: Must be of type number and a floating point number.
  • array: Must be an array as determined by Array.isArray.
  • object: Must be of type object and not Array.isArray.
  • enum: Value must exist in the enum.
  • date: Value must be valid as determined by Date
  • url: Must be of type url.
  • hex: Must be of type hex.
  • email: Must be of type email.
  • any: Can be any type.

Required

The required rule property indicates that the field must exist on the source object being validated.

Pattern

The pattern rule property indicates a regular expression that the value must match to pass validation.

Range

A range is defined using the min and max properties. For string and array types comparison is performed against the length, for number types the number must not be less than min nor greater than max.

Length

To validate an exact length of a field specify the len property. For string and array types comparison is performed on the length property, for the number type this property indicates an exact match for the number, ie, it may only be strictly equal to len.

If the len property is combined with the min and max range properties, len takes precedence.

Enumerable

Since version 3.0.0 if you want to validate the values 0 or false inside enum types, you have to include them explicitly.

To validate a value from a list of possible values use the enum type with a enum property listing the valid values for the field, for example:

const descriptor = {
  role: { type: 'enum', enum: ['admin', 'user', 'guest'] },
};

Whitespace

It is typical to treat required fields that only contain whitespace as errors. To add an additional test for a string that consists solely of whitespace add a whitespace property to a rule with a value of true. The rule must be a string type.

You may wish to sanitize user input instead of testing for whitespace, see transform for an example that would allow you to strip whitespace.

Deep Rules

If you need to validate deep object properties you may do so for validation rules that are of the object or array type by assigning nested rules to a fields property of the rule.

const descriptor = {
  address: {
    type: 'object',
    required: true,
    fields: {
      street: { type: 'string', required: true },
      city: { type: 'string', required: true },
      zip: { type: 'string', required: true, len: 8, message: 'invalid zip' },
    },
  },
  name: { type: 'string', required: true },
};
const validator = new Schema(descriptor);
validator.validate({ address: {} }, (errors, fields) => {
  // errors for address.street, address.city, address.zip
});

Note that if you do not specify the required property on the parent rule it is perfectly valid for the field not to be declared on the source object and the deep validation rules will not be executed as there is nothing to validate against.

Deep rule validation creates a schema for the nested rules so you can also specify the options passed to the schema.validate() method.

const descriptor = {
  address: {
    type: 'object',
    required: true,
    options: { first: true },
    fields: {
      street: { type: 'string', required: true },
      city: { type: 'string', required: true },
      zip: { type: 'string', required: true, len: 8, message: 'invalid zip' },
    },
  },
  name: { type: 'string', required: true },
};
const validator = new Schema(descriptor);

validator.validate({ address: {} })
  .catch(({ errors, fields }) => {
    // now only errors for street and name    
  });

The parent rule is also validated so if you have a set of rules such as:

const descriptor = {
  roles: {
    type: 'array',
    required: true,
    len: 3,
    fields: {
      0: { type: 'string', required: true },
      1: { type: 'string', required: true },
      2: { type: 'string', required: true },
    },
  },
};

And supply a source object of { roles: ['admin', 'user'] } then two errors will be created. One for the array length mismatch and one for the missing required array entry at index 2.

defaultField

The defaultField property can be used with the array or object type for validating all values of the container. It may be an object or array containing validation rules. For example:

const descriptor = {
  urls: {
    type: 'array',
    required: true,
    defaultField: { type: 'url' },
  },
};

Note that defaultField is expanded to fields, see deep rules.

Transform

Sometimes it is necessary to transform a value before validation, possibly to coerce the value or to sanitize it in some way. To do this add a transform function to the validation rule. The property is transformed prior to validation and returned as promise result or callback result when pass validation.

import Schema from 'async-validator';
const descriptor = {
  name: {
    type: 'string',
    required: true,
    pattern: /^[a-z]+$/,
    transform(value) {
      return value.trim();
    },
  },
};
const validator = new Schema(descriptor);
const source = { name: ' user  ' };

validator.validate(source)
  .then((data) => assert.equal(data.name, 'user'));

validator.validate(source,(errors, data)=>{
  assert.equal(data.name, 'user'));
});

Without the transform function validation would fail due to the pattern not matching as the input contains leading and trailing whitespace, but by adding the transform function validation passes and the field value is sanitized at the same time.

Messages

Depending upon your application requirements, you may need i18n support or you may prefer different validation error messages.

The easiest way to achieve this is to assign a message to a rule:

{ name: { type: 'string', required: true, message: 'Name is required' } }

Message can be any type, such as jsx format.

{ name: { type: 'string', required: true, message: '<b>Name is required</b>' } }

Message can also be a function, e.g. if you use vue-i18n:

{ name: { type: 'string', required: true, message: () => this.$t( 'name is required' ) } }

Potentially you may require the same schema validation rules for different languages, in which case duplicating the schema rules for each language does not make sense.

In this scenario you could just provide your own messages for the language and assign it to the schema:

import Schema from 'async-validator';
const cn = {
  required: '%s εΏ…ε‘«',
};
const descriptor = { name: { type: 'string', required: true } };
const validator = new Schema(descriptor);
// deep merge with defaultMessages
validator.messages(cn);
...

If you are defining your own validation functions it is better practice to assign the message strings to a messages object and then access the messages via the options.messages property within the validation function.

asyncValidator

You can customize the asynchronous validation function for the specified field:

const fields = {
  asyncField: {
    asyncValidator(rule, value, callback) {
      ajax({
        url: 'xx',
        value: value,
      }).then(function(data) {
        callback();
      }, function(error) {
        callback(new Error(error));
      });
    },
  },

  promiseField: {
    asyncValidator(rule, value) {
      return ajax({
        url: 'xx',
        value: value,
      });
    },
  },
};

validator

You can custom validate function for specified field:

const fields = {
  field: {
    validator(rule, value, callback) {
      return value === 'test';
    },
    message: 'Value is not equal to "test".',
  },

  field2: {
    validator(rule, value, callback) {
      return new Error(`${value} is not equal to 'test'.`);
    },
  },
 
  arrField: {
    validator(rule, value) {
      return [
        new Error('Message 1'),
        new Error('Message 2'),
      ];
    },
  },
};

FAQ

How to avoid global warning

import Schema from 'async-validator';
Schema.warning = function(){};

or

globalThis.ASYNC_VALIDATOR_NO_WARNING = 1;

How to check if it is true

Use enum type passing true as option.

{
  type: 'enum',
  enum: [true],
  message: '',
}

Test Case

npm test

Coverage

npm run coverage

Open coverage/ dir

License

Everything is MIT.

More Repositories

1

learning-react

materials about learning react
HTML
551
star
2

dom-align

Align DOM Node Flexibly
JavaScript
374
star
3

dom-scroll-into-view

scroll dom node into view automatically
JavaScript
155
star
4

tyarn

yarn using npm.taobao.org as registry
JavaScript
127
star
5

koa-webpack-dev-middleware

webpack dev middleware for koa
JavaScript
92
star
6

css-animation

make css animation easier
JavaScript
89
star
7

zscroller

dom scroller based on zynga scroller
JavaScript
48
star
8

react-worker-render

move react component lifecycle to worker and render to DOM
TypeScript
42
star
9

kison

A LALR(1)/LL(1)/LL(K) parser generator for javascript/typescript
TypeScript
39
star
10

add-dom-event-listener

add dom event listener. normalize ie and others
JavaScript
39
star
11

xhr-plus

XMLHttpRequest Plus. Support jsonp, form upload, sub domain proxy and more...
JavaScript
29
star
12

tree-diff

diff tree nodes like React
JavaScript
22
star
13

gregorian-calendar

gregorian calendar lib on browser and nodejs
JavaScript
20
star
14

reverse-proxy

A simple reverse proxy
JavaScript
20
star
15

web-to-react-native-style

transform web style to react-native style
TypeScript
19
star
16

react-data-binding

React Data Binding Library
JavaScript
19
star
17

react-scoped-style

scope react element by transform external style into inline styles
JavaScript
18
star
18

match-require

find require calls from string using regexp
JavaScript
17
star
19

gregorian-calendar-format

format gregorian-calendar
JavaScript
16
star
20

leetcode-solutions

solutions of leetcode
JavaScript
14
star
21

lab

yiminghe's lab
JavaScript
14
star
22

koa-serve-index

koa version of express serve index middleware
JavaScript
13
star
23

react-fiber-worker

react running inside worker
JavaScript
10
star
24

ot-engine

Operational transformation engine
TypeScript
10
star
25

query-selector

querySelectorAll in javascript
JavaScript
10
star
26

falcor-koa-router

falcor router middleware for koa
JavaScript
9
star
27

map-json-webpack-plugin

webpack plugin to generate md5-source map.json
JavaScript
8
star
28

saucelabs-runner

wrap wd and sauce-tunnel to test mocha runner across browsers
JavaScript
8
star
29

single-spa-mf

A micro frontend solution based on single-spa and module federation
TypeScript
7
star
30

falcor-todo-demo

todo demo using falcor and redux-saga
JavaScript
7
star
31

ot-tree

The Tree OT type can be used to edit arbitrary Tree Structure
TypeScript
7
star
32

node-jscover

node version of JSCover
JavaScript
6
star
33

yiminghe.github.com

HTML
6
star
34

simulate-dom-event

simulate dom event across browser
JavaScript
6
star
35

chrome-map-remote

A chrome extension providing map remote functionality like charles
JavaScript
6
star
36

gh-history

generate HISTORY.md
JavaScript
6
star
37

kissy-boilerplate

boilerplate for kissy project
JavaScript
5
star
38

class-id-minifier

minifier class and id attribute in html
JavaScript
5
star
39

micro-front-end-nextjs

make nextjs works with micro front end
TypeScript
4
star
40

rbtree

javascript red-black tree
TypeScript
4
star
41

versioned-react-ssr

server side render react component by react version
TypeScript
3
star
42

suffix-tree

Ukkonen's suffix tree algorithm
TypeScript
3
star
43

versioned-vue-ssr

server side render vue component by vue version
JavaScript
3
star
44

offlinekit

offline toolkit using service worker
TypeScript
3
star
45

react-refresh-loader

webpack loader for react-refresh
JavaScript
2
star
46

ios-todo-demo

ios todo demo using yoga and without storyboard
C
2
star
47

concurrent-runner

run cancelable async function concurrently by concurrency and priority using heap
TypeScript
2
star
48

game-eidolon

An experimental webgl/2d game
JavaScript
2
star
49

node-jscover-coveralls

a middleware to send coverage data on phantomjs by node-jscover to coveralls
JavaScript
2
star
50

pika-plugin-clean-dist-src

remove dist-src and correct package.json
JavaScript
2
star
51

koa-webpack-dev-test-server

server for dev, test and coverage for koa and webpack
JavaScript
2
star
52

pika-plugin-build-web-babel

using babel for @pika/plugin-build-web
JavaScript
2
star
53

react-native-index-page

index page for list of components demo
JavaScript
1
star
54

monaco-editor-webpack-plugin-2825

JavaScript
1
star
55

get-async

get something asynchronously without repetition
TypeScript
1
star
56

kissy-dpl

JavaScript
1
star
57

ts-event-target

EventTarget from nodejs with full typescript type support.
TypeScript
1
star
58

react-pixi-layer

support layer render with pixi.js by using multiple canvas
JavaScript
1
star
59

babel-runtime-loose

loose version of babel-runtime
JavaScript
1
star
60

eslint-plugin-catch-call-function

enforce call function inside catch clause
JavaScript
1
star
61

bit-components

some bit components
TypeScript
1
star
62

koa-modularize

koa middleware for transforming commonjs file into browser module format
JavaScript
1
star
63

node-jscover-webpack-loader

webpack loader for node-jscover
JavaScript
1
star
64

nest-web

use nestjs DI on web
TypeScript
1
star
65

pika-plugin-ts-types

A @pika/pack plugin: generate typescript types to dist-types
JavaScript
1
star
66

kissy-chrome-extension

using kissy in chrome extension
JavaScript
1
star