rsuite / validation

:sunglasses: Validate like a boss.
10 stars 4 forks source link

@rsuite/validation

Validate like a boss.

Node.js CI npm version

npm install -S @rsuite/validation

Features

Usage

Validate data

import { Validator } from "@rsuite/validation";

const checkResult = Validator.check(data, {
  name: "required",
  email: "required|email",
  age: "number|between:18,30",
});

Create SchemaModel for <Form> component

import { Validator } from "@rsuite/validation";

const model = Validator.SchemaModel({
  name: "required",
  email: "required|email",
  age: "number|between:18,30",
});

Validate array items and object properties

import { Validator } from "@rsuite/validation";

const validator = Validator.make({
  "pet.name": "required", // Auto-detects `pet` as an object of shape { name: string }
  "luckyNumbers.*": "number", // Auto-detects `luckyNumbers` as an array, whose items should be numbers
  "cars.*.price": "number|min:1000000000", // Auto-detects `cars` as an array of objects of shape { price: number }
});

On the other hand, if your field name contains a literal period, you can explicitly prevent this from being interpreted as "dot" syntax by escaping the period with a backslash:

import { Validator } from "@rsuite/validation";

const validator = Validator.make({
  "v1\\.0": "required",
  "object\\.withDot.property": "required", // { 'object.withDot' : { property }}
  "anotherObject.withDot\\.inProperty": "required", // { anotherObject: { 'withDot.inProperty' }}
});

Custom error messages

You can override error message for any rule, or for any rule on any field specifically.

import { Validator } from "@rsuite/validation";

const validator = Validator.make(
  {
    name: "required",
    email: "required|email",
    age: "required|number|between:18,30",
  },
  {
    required: "You should not omit {field}!",
    "email.required"(field) {
      return "Email is a must.";
    },
    "age.between": "Age should be between {min} and {max}",
    fields: {
      email: "Email address",
    },
  }
);

Learn more in Error messages.

Custom rules

import { Validator } from "@rsuite/validation";

const validator = Validator.make({
  name: [
    "required",
    {
      check(field, value, data) {
        return value === "Tom";
      },
      errorMessage: "Only whose {field} is Tom shall pass.",
    },
  ],
});

Learn more in Custom validation rules.

API

Validator

import { Validator } from '@rsuite/validation

Error messages

@rsuite/validation is packed with predefined messages for every built-in rules. You can define your own messages for Validator, either per rule or per rule per field.

const validator = Validator.make(
  {
    name: "required",
    email: "required|email",
    age: "required|number|between:18,30",
  },
  {
    required: customMessage1,
    "age.between": customMessage2,
  }
);

A custom message should be either a string or a ErrorMessageFormatter.

interface ErrorMessageFormatter {
  (field: string, placeholderValues?: any): string;
}

If you want to customize how your field names are displayed in the error messages (by default is capitalized), set them in field property of the message bag.

const validator = Validator.make(
  {
    name: "required",
    email: "required|email",
    age: "required|number|between:18,30",
  },
  {
    required: "Please enter {field}",
    fields: {
      email: "Email address",
    },
  }
);

Defined messages globally

Use Validator.messages() to register message bag globally.

Validator.messages({
  required: "Please enter {field}.",
});

Placeholders

You can use placeholders (marked with brackets) in your error message string. Note that you can only use them when your error message is a string, not a formatter function.

const messages = {
  required: "{field} is required.",
  min: "{field} must be no smaller than {value}.",
};

Each rule has different placeholders available, while {field} is available across all rules, representing the field name declared in your rules object. Most placeholders have the same name as the rule signature. Here is a full list of built-in rules that have placeholders in messages.

Rule signature Placeholders
size:value {value}
max:value {value}
min:value {value}
between:min,max {min}, {max}
gt:other {other}, {value}
gte:other {other}, {value}
lt:other {other}, {value}
lte:other {other}, {value}
same:other {other}
different:other {other}
in:value1,value2... {values}
notIn:value1,value2... {values}
unique:by? {by}
regex:pattern {pattern}
after:date {date}
afterOrEqual:date {date}
before:date {date}
beforeOrEqual:date {date}
endsWith:value1,value2... {values}
startsWith:value1,value2... {values}

If you use ErrorMessageFormatter, placeholders values are passed in as an object to its second argument.

Available rules

Type rules

@rsuite/validation has 6 supported types. Some rules are effective among all these types, some are only effective under specific types.

Validation rules

Custom validation rules

In addition to built-in validation rules, you can also define you own validation rules.

Validator.make({
  name: ["required", customRule1, customRule2],
  email: ["required", "email", customRule3],
});

A custom rule must implement Rule interface.

interface Rule {
  /**
   * Check whether the value passes this rule
   */
  check(field: string, value: any, data: any): boolean;

  /**
   * Message to show when this rule fails.
   */
  errorMessage: string | ErrorMessageFormatter;
}

@rsuite/schema-typed API coverage

The table below shows @rsuite/schema-typed API and their equivalent rules in @rsuite/validation. Note that equivalent means equivalent, which is, implementation of the rule is calling the according API or copies its underlying implementation. Those APIs that don't have an equivalent rule for now (marked as -) can still be achieved using Custom validation rules.

API Rule
.isRequired() required
.addRule() Custom validation rules
API Rule
StringType() string
.isEmail() email
.isURL() url
.isOneOf(items) in:value1,value2...
.containsLetter() regex:[a-zA-Z]
.containsUppercaseLetter() regex:[A-Z]
.containsLowercaseLetter() regex:[a-z]
.containsLetterOnly() regex:^[a-zA-Z]+$
.containsNumber() regex:[0-9]
.pattern(regExp) regex:pattern
.rangeLength(minLength, maxLength) between:min,max
.minLength(minLength) min:value
.maxLength(maxLength) max:value
API Rule
NumberType() number
.isInteger() integer
.isOneOf(items) in:value1,value2...
.pattern(regExp) regex:pattern
.range(min, max) between:min,max
.min(min) min:value
.max(max) max:value
API Rule
ArrayType() array or auto-detect from field expression
.rangeLength(minLength, maxLength) between:min,max
.minLength(minLength) min:value
.maxLength(maxLength) max:value
.unrepeatable() unique
.of(type) Wildcard field expression
API Rule
DateType() date
.range(min,max) afterOrEqual:min | beforeOrEqual:max
.min(min) afterOrEqual:date
.max(max) beforeOrEqual:date
API Rule
ObjectType() object or auto-detect from field expression
.shape(type) Auto-detect from field expression
API Rule
BooleanType() boolean

Philosophy

Prior Art

License

MIT Licensed.