react-input-validator

Documentation

It’s common in an application that the user needs to fill the inputs or choose the options. There are some components that becomes the interface for user to make an input such as text box, radio button, check box, combo box etc. Sometimes, the user inputs needs validation before being saved into database or continuing to the next process to make the application works correctly.

This package is to validate the input component and if the input value is invalid then an error message will be shown near the input component. If the value is valid, optionally, the clue that tells the value is valid can also be shown. The following picture below depicts some examples how the error messages are displayed.

validation for different types of inputs

More fancy example which uses an icon to reflect the validation status:

validation with status icon

It can also validate the uploaded files:

file upload

How To Install

npm i rc-input-validator --legacy-peer-deps

The Comparison between rc-input-validator and The Other System

Here, we explain the comparison with the other package or even the built-in validation stuff in HTML DOM (Document Object Model). Not trying to compete those systems but rc-input-validator tries to fill the untouched gap.

Schema-based validator

This kind of validator is quite popular. Therefore, we talk about it here. The example of this kind of validator are zod and ajv. These validators can validate a simple data up to a complex nested object. Whereas, in the other hand, rc-input-validator can only validate the simple values. It’s because this package is designed to validate the inputs inside the form that will be submitted to the server. In fact, the form inputs retain the simple value, mostly a string or an array of string.

Another fact, the object of schema validator is the data itself. Whereas, the object of rc-input-validator is the input components (the User Interface widget/control) which is indirectly the data retained by the input components. So, what is the different? rc-input-validator can show the error message near the invalid input component and change their styling (appearance) whether they are invalid or valid.

Actually, rc-input-validator can also to validate the data directly. But it’s likely you prefer to use schema-based validator for web API service.

Built-in HTML DOM (Document Object Model) validation stuff

The recent HTML DOM is equipped with a lot of stuff for the form inputs validation. I think, for basic to intermediate needs, it’s enough for you. Even you don’t need write any script because the form inputs are automatically validated just before submitted. If any invalid input, the form won’t be submitted.

You may set the validation via attributes: required, pattern, min, max, minlength, maxlength etc. Some values for type attribute are also available for some special input data type, such as date, time, number, url etc. If the value entered by user is not in a proper format for those special data types, the input will be considered as invalid. When the validation event happens, an error message will be shown according to what constraint has been violated. In addition, you may set a custom message by invoking setCustomValidity method (in this case, you must write a script).

For input styling, there are some CSS pseudo classes that can be used. You may use :invalid or :valid. Also, :required may be useful.

Now, we talk about the conditions in which you may prefer rc-input-validator

These conditions happen, at least on all browsers I’ve known (Edge, Chrome, Firefox, Safari)

A Brief Example

React Native App

import React from 'react';
import {
    Button,
    StyleSheet,
    Text,
    TextInput,
    View,
} from 'react-native';
import {
    ValidationContext,
    withValidation,
} from "rc-input-validator/native";
import {
    email,
    required,
} from 'rc-input-validator/rules';
import server from './server';

const UserName = withValidation(TextInput, {
    rules: [email, required],
});
const Password = withValidation(TextInput, {
    rules: required,
});

export default function LoginForm() {
    const validationRef = React.createRef();
    const [userName, setUserName] = React.useState('');
    const [password, setPassword] = React.useState('');
    
    return (
        <ValidationContext ref={validationRef}>
            <Text style={styles.title}>Please login:</Text>
            <UserName autoCorrect={false} onChangeText={setUserName} placeholder="Email" style={styles.input} value={userName} />
            <Password onChangeText={setPassword} placeholder="Password" secureTextEntry style={styles.input} value={password} />
            <View style={styles.buttonRow}>
                <Button
                    onPress={() => {
                        if (validationRef.current?.validate()) {
                            server.login(userName, password);
                        }
                    }}
                    title="Login"
                />
            </View>
        </ValidationContext>
    );
}

const styles = StyleSheet.create({
    buttonRow: {
        flexDirection: 'row',
        justifyContent: 'flex-end',
    },
    input: {
        borderColor: '#ccc',
        borderRadius: 4,
        borderWidth: 1,
        color: 'black',
        marginBottom: 10,
    },
    title: {
        marginBottom: 10,
    },
});

In this example, you may concern to withValidation and ValidationContext most. At a glance, you may have concluded that withValidation is to specify the validation rules for the input and ValidationContext is to validate all inputs inside it. Actually, each input can be validated individually and doesn’t need to be put inside ValidationContext (see detailly here). ValidationContext exists to validate many inputs at once.

React Web App

import React from 'react';
import {
    Form,
    Input,
} from "rc-input-validator/web";
import {
    email,
    required,
} from 'rc-input-validator/rules';

export default function LoginForm() {
    return (
        <Form action='/login' method='POST'>
            <h3>Please login:</h3>
            <Input rules={[email, required]} type='text' name='usename' placeholder="Email" />
            <Input rules={required} type='password' name='password' placeholder="Password" />
            <div style=>
                <button type='submit'>Login</button>
            </div>
        </Form>
    );
}

React web app looks more simple. There are Form and Input element. Input is replacement of withValidation in React Native app. It extends the original input elenent. It adds rules props to it. Form extends the original form element. It wraps ValidationContext that should be placed next to form element. For detail explaination, please read Form and Input section.

API Reference

Package Structure

This package consists of some modules as the entry points to access the objects provided by this package. Generally, you must import the components for React Native app from “native” module. The components for web app are imported from “web” module. The rule objects are from “rules” module.

The more complete list below shows the modules and the objects exported from them:

ValidationContext

For React Native, it’s imported from "rc-input-validator/native"
For React web, it’s imported from "rc-input-validator/web"

This element can validate all contained Input, TextArea, Select or inputs that have been set by withValidation. Also, it can clear the validation status of those inputs.

For web app, you may prefer Form

Some props that can be set for this element are:

Methods and property of ValidationContext reference (the object that we get from ref prop):

Form

In web app, ValidationContext should be placed next to form element to cover all inputs that will be submitted to the server. Because of this, Form component exists to wrap both components, ValidationContext and form. By using onSubmit event, Form component arranges ValidationContext to execute validation. If any invalid input, the sumbit event will be cancelled.

Coupling ValidationContext and form element is not a must. If you have another purpose, you may place ValidationContext element wherever you want.

Form element has all props of form element, except noValidate. Built-in validation is always disabled because rc-input-validator takes in charge now. Beside form props, there is an additional prop:

Methods and properties

Form component has all members of ValidationContext and also all members of form.

Input Component

An input that will be validated must be prepared, mainly, it must apply some validation rules. An input can be validated individually or in a group. To validate a group of inputs, they must be put in a ValidationContext.

For React Native app, an input is prepared by withValidation. For web app, there are some components that mimic the HTML input elements. Technically, they prepare the represented HTML input element when mounted (prepared just once, not every render/update) so that the input can be validated.

Input validation options/settings

To prepare an input, there are some option properties that can be set to determine the behavior of validation. For React Native, these option properties are assigned to the second parameter of withValidation function. For web, these validation options are assigned to settings prop of the input.

The list of input validation option properties:

Beside the properties above, below are some properties which are only available for withValidation (there is a note for each property why it doesn’t exist for web input):

withValidation

This function is to create a higher-order component that wraps an input component so that it can apply some validation rules and also some attributes needed to define the behavior. You can see in the example above that this function takes two parameters. The first parameter is the function/class component that will be validated.

The second parameter is the option object. The object has some properties which specify validation rules and the other attributes. The only property you must specify is rules. The other properties are optional. If you only need to set the validation rule(s) for the input, the second parameter can be a rule object or an array of rule objects.

This function is available for React Native app.

Web input

For web app, there some input components that is automatically validated. Some of these inputs mimic the standard form inputs. These inputs generally have the same props/attributes as HTML inputs. However, there are some differents:

The available input components:

Input, Select and TextArea

Input, Select and TextArea represents HTML input, select and textarea respectively. They have the same props as ones owned by their represented HTML element except some notes explained by above paragraph.

Data type of value prop of Input mostly is string. If type prop is number or range, value data type is number. If type prop is file, don’t you set value prop but if you set onChange handler, event.target.value will be an array of File.

Data type of value prop of Select is string by default. If multiple prop is set, value data type is an array of string.

CheckBoxes

CheckBoxes is a group of some <Input type='checkbox' /> whose the same name prop. Sometimes, this input is preferred representation of <Select multiple> if there are only the slight number of options. This conponent has the following props:

Available CheckBoxes method:

Example:

<CheckBoxes
  rules={alwaysValid}
  options={['Music', 'Movie', 'Sport', 'Other']}
  value={['Music', 'Movie']}
/>

The above example will show four checkboxes labeled as ‘Music’, ‘Movie’, ‘Sport’ and ‘Other’ with ‘Music’ and ‘Movie’ are checked.

RadioButtons

RadioButtons is a group of some <Input type='radio' /> whose the same name prop. In fact, radio input should be in a group to make a choice. Sometimes, this input is preferred representation of <Select> if there are only the slight number of options. This component has props/method as the same as the props/method of CheckBoxes except value data type is always a string.

Example:

<RadioButtons
  horizontal
  options={[
    {value: 'M', label: 'Male'},
    {value: 'F', label: 'Female'},
  ]}
  rules={required}
  value='M'
/>

The above example will show two radio buttons labeled as ‘Male’ and ‘Female’ with ‘Male’ is checked.

ValidatedInput

If the above inputs are not enough, ValidatedInput gives you a freedom to define an input. Beside rules and settings prop, ValidatedInput has Component prop. The last prop is an input component. You can assign your custom input component to this prop. The rest props (other than rules, settings and Component) assigned to ValidatedInput element will be delegated to the input element defined by Component prop.

Component prop is only read at mounting. In the next renders, this prop is ignored.

Methods and properties of the input reference (the object that we get from ref prop):

If the original input has the same methods and property as listed above, they will be overriden. If you want to access the overridden method/property of original input, follow the example below:

const inputRef = React.useRef();
...
<Input ref={inputRef} onBlur={() => {
    //This statement will validate the input
    inputRef.current.validate();
    
    //This statement will invoke `validate` method of original input
    inputRef.current.__proto__.validate();
}} ... />

Validation Component

For React Native, it’s imported from "rc-input-validator/native"
For React web, it’s imported from "rc-input-validator/web"

Validation component can be used to validate a value without wrapping an input component. It has some properties which are the same as withValidion option. These properties are auto, errorTextStyle, lang and rules. The purpose of these properties are exactly the same as withValidion option’s. These properties are write-once. They are only set when the component is mounted. If you change the properties in the next render, it won’t have effect.

Beside the properties mentioned before, there are two more properties:

Validation object reference also has the same methods and property as those owned by input component reference resulted by withValidation

Example:

import React from 'react';
import {... TextInput, ...} from 'react-native';
import {Validation, ValidationContext} from "rc-input-validator/native";
import {email, required} from 'rc-input-validator/rules';
...

export default function Form() {
    ...
    const [emailAddress, setEmailAddress] = React.useState('');
    ...

    return (
        <ValidationContext ref={validation}>
            ...
            <TextInput onChangeText={setEmailAddress} placeholder="Email" value={emailAddress} />
            <Validation rules={[required, email]} value={emailAddress} />
            ...
        </ValidationContext>
    );
}

You notice this example, the value of Validation is the same as the value of email TextInput. By this way, it’s like to apply the use of withValidation to the email TextInput.

Style Handling

React Native

To make the input and the error message stick together, withValidation wraps them into a Container component. However, we want the component yielded by withValidation behaves the same as the original input except we add the validation feature to it. All properties for the input must apply for the new component. Every property seems ok, we can just distribute them to the wrapped input. Except one property we think it has a problem. That is the property which defines the style for the input. Because now, the input is inside the Container. We must modify the style property if we still want the same style as if the input is unwrapped. The big concern is all style attributes dealing with layout. That is how the parent of input arranges the area for input, before. Because now, the parent must arrange the Container. Therefore, the component yielded by withValidation will move all style attributes dealing with layout to be the style attributes of Container. Then, the input must be set to fill the area of Container.

We know, the value for style prop is not always a plain object or a falsy value but it can be a recursive array. Therefore, the first step is to flatten it if it’s an array. Fortunately, React Native has provided StyleSheet.flatten function to do that. After getting a single plain object, the following style attributes will be assigned to the Container:

Some other attributes will be moved to the Container under a condition:

To make sure the input fills the area of the Container, its flex attribute is set to 1 if the Container has one of attributes: height (percentage), flex or flexBasis. But if the input has height (number) attribute, the flex attribute won’t be set.

There are two handlers you may define in withValidtion option which involves in this modification of style. Those are getStyle and setStyle.

There is still a possibility that the layout will mess up when the error message comes up. That possibility happens, especially when the parent of input (that becomes the parent of the Container) lays its children horizontally (flexDirection is row). To avoid it, you should set a fixed height (not percentage) for the input.

The process explained above is executed in every render. To increase performance, it must be sure that the process is run only if the style value changes. To do that, the package has isDifferentStyle function. You can import this function for your own purpose. This function does more detailedly than a shallow compare. Let’s explain in the example below:

const style1 = {flex: 2},
      style2 = {flex: 3};
isDifferentStyle(style1, style2); //return true
isDifferentStyle(style1, [style1]); //return false
isDifferentStyle([style1], [style1]); //return false
isDifferentStyle([style1, style2], [style1, style2]); //return false
isDifferentStyle([style1, style2], [style2, style1]); //return true
isDifferentStyle(style1, [style2]); //return true
isDifferentStyle([style1], [style1, style2]); //return true

So, the function simply just compares the entry in the array at the same index. The more detailedly logic can be done to make sure that they are really different but it can cause a more complicated process that won’t help increasing performance.

To help increasing performance, you must also set the style value to a constant value, not variable. For example:

const styles = StyleSheet.create({
    input: {borderWidth: 1, ...},
    hightlight: {...},
});
const Input = withValidation(TextInput, ...);
...
export default function Form(props) {
    ...
    return (
        ...
        //It's BAD example
        <Input style= ... />

        //It's good
        <Input style={styles.input} ... />

        //If you want to make a different style for
        //a condition, it's a good example
        <Input style={[
            styles.input,
            highlighted ? styles.hightlight : null,
        ]} ... />
        ...
    );
}

React Web

Firstly, this package was designed for React Native. But then, the writer thought that there is a need to port the package for React web. There is a big obstacle to rewrite this package to support web app that is the style handling. The style in web, which is called CSS (Cascading Style Sheet) is very complicated. There are many shorthand CSS properties. A shorthand CSS property represents some other specific properties. It’s not simple process to parse. Therefore, we use the different approach for React web, the style must be explicitly set to the input and its Container.

Beside that, an element style is determined by a lot of selectors: tag/element name, the existence or the value of a prop/attribute or even by the parent/ancestor element and the sibiling elements. However, the are two main props to define the style: className and style. This package will focus on those two props.

Based on the above explanation, we make the following approach. Let’s say we define StyleProp that is the data type for style prop of individual component (the input or its Container). A validated input that is a composite component (the original input and its Container) has style prop whose type as follows:

{ $cover: StyleProp, $input?: StyleProp } | StyleProp

$cover is for Container and $input for the original input component. An alternative way is we can assign a StyleProp value to style prop. It means we want to set the input only and let Container uses the default style. StyleProp itself is defined as follows:

string | CSSProperties | { $class: string, $style: CSSProperties }

If it’s string then it’s the CSS class name(s) (will be assigned to className prop of the underlying HTML element). If it’s CSSProperties then it’s inline style (will be assigned to style prop of underlying HTML element). If we want to set both, we use {$class, $style}. This package provides getStyleProps function to convert StyleProp or array of StyleProp to be {className, style} object. This function may be useful if you want to implement setStatusStyle function.

Asynchronous Validation

In some cases, we need to execute the validation process in asynchronous mode. The prominent example is when we need to call back the server to check the validity of input value. May be, we need to check the database to ensure the input is valid or not. For making an HTTP request purpose, this package has provided httpReq rule.

To make the process of validation in asynchronous mode, first thing you need is a rule object that can validate a value asynchronously. This package has provided some rule objects that can make the process asynchronously. One of them has been mentioned before, that is httpReq. The another one is ruleAsync. If these rule objects don’t satisfy you, create your own rule class which inherits ValidationRuleAsync class.

After you defines the asynchronous rule(s), as usual, set the rule(s) to rules option of withValidation or rules prop of the web input. You may mix asynchronous and synchronous rules. priority property still applies as appropriately (an asynchronous rule won’t be examined after a synchronous rule that has lower priority).

The last step, to validate the input(s) asynchronously, you must call validateAsync method of the input reference or validateAsync method of the context reference. Both methods return a Promise object. So, if you want to get the validation result, you should use the following statement:

inputRef.validateAsync()
    .then(isValid => {
        //... rest of your code
    });

or

let isValid = await inputRef.validateAsync();

The last statement must be inside an async function.

Server-side Validation

rc-input-validator pakcage is to validate inputs in React Native app or an HTML form. In other words, it’s for client-side validation. By existence of client-side validation, we are more confident to submit data to the server. However, is it enough? Absolutely not. A hacker can make a request without using our app and use an invalid data. So, the server-side validation is always needed exactly as if we are not using a rich user interface application (like an oldish web app).

Then, you may think that if we use a rule like httReq then the server-side validation has been done because the validation by this rule is examined on the server. Unfortunately, it’s not. We must validate the inputs right before they are used by the corresponding business process. Clearly, the URI used by httpReq is different from that to where the data is submitted. Knowing this fact, you may think that a rule like httReq is not needed because there will be more round-trip. Yes, you are true but people always have different preference and there may be a situation it’s needed.

Now, if we agree that the server-side validation is needed then how to notify user if there is one or more invalid inputs. You may use an alert dialog or a Toast popup. But, it may be better if we show each error message below the corresponding input with hightlighting style like this package does in client-side validation. It’s possible by the favor of setErrorMessage method. Follow the example below. In the example, if there is one or more invalid inputs, the server returns status code 400 (Bad Request) and the response body is a JSON data key-ed by the invalid input names. The value of each key is the error message for that input.

    <Button
        onPress={() => {
            function okAction() {
                //The code to be executed when all inputs are valid ...
            }

            fetch('https://yourserver.com/check-password', {
                body: JSON.stringify({passord, confirmPassword}),
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                }
            })
            .then(async (response) => {
                if (response.ok) okAction();
                else if (response.status == 400) {
                    const errors = await response.json();
                    for (let inputName in errors) {
                        contextRef.current.setErrorMessage(inputName, errors[inputName]);
                    }
                    if (contextRef.current.isValid) {
                        //Although, the response status is invalid but no error message provided.
                        //Therefore, we consider all inputs are valid.
                        okAction();
                    }
                }
                else {
                    Alert.alert('Validation', 'Server response is not OK');
                }
            })
            .catch(() => {
                Alert.alert('Validation', 'An error happened.');
            })
        }}
        title="Validate on server"
    />

To keep consistency, the logic used for the server-side validation must be the same as that used by client-side validation. If you use Node server, you may use rc-input-validator pakcage. However, if without TypeScript, you should import the rule objects and the needed fuctions from “dist” directory. For example:

    const {
        validate
    } = require("rc-input-validator/dist/helpers");
    const {
        required,
        rule,
        length,
    } = require('rc-input-validator/dist/rules');

To validate an input, follow the example below:

    const passwordRules = [
        required,
        length(8),
        rule(
            value => {
                return /[a-z]/.test(value) && /[A-Z]/.test(value) && /[0-9]/.test(value) && /[^a-zA-Z\d\s]/.test(value);
            },
            'The password must contain capital and non capital letter, number and non-alphanumeric characters'
        ),
    ];
    errMsg = validate(inputValue, passwordRules, inputName);
    if (typeof(errMsg) == 'string') {
        errors[inputName] = errMsg; //the error message is collected for the response data
    }

Asynchronous validation is still needed in server-side validation, for example, if we need to connect to database to check the validity of input. Database connection is usually in asynchronous mode.

Functions

The functions here can be imported from the package.

getStyleProps(...styles)

This function is provided by “web” module. This function converts StyleProp value as described in this section to be a value whose type:

{className: string | undefined, style: CSSProperties | undefined}

so that it can be assigned as the props of an HTML element. This function can more than one parameter or an array:

getStyleProps(style1, style2, ...)

The resulted value will have all CSS classes defined by all parameters. For inline style, if there is the same CSS property from different parameter, the property value from the parameter on the right will override the one from the parameter on the left.

isFilled(value)

This function is used by required rule to check whether a value is empty or not. A value is considered as empty if it is null, undefined, a string only contains white space(s) or an empty array. An array containing only one empty element is also considered empty. This funtion returns false if value is empty.

str(template, valueMap)

This function is to construct a string from a template string and a map of values. In the template string contains the placeholders for variables to be replaced by the real value. The placeholder is in format ${variable_name}. The real values is in valueMap parameter. For example:

str('${name} must be at least ${min}', {name: 'count', min: 5})

will return string "count must be at least 5".

Rule Object

Rule object defines how to validate the input value. For example whether it’s required (cannot be empty), must be a numeric value, must be minimum at a certain value etc. The rule object is reponsible to check whether the input value meets the desired condition or not, to be valid. Mostly, one rule object is responsible to check only one condition. However, we can combine some rule objects so that the input value must meet some conditions to be valid. This is why withValidation rules option can be a single rule object or an array of rule objects.

This package has some built-in rule objects which are ready to use. These rule objects are explained in the next sections. You can create your own rule object by creating a class that extends ValidationRule or ValidationRuleAsync. Most rule objects are imported from 'rc-input-validator/rules'.

ValidationRule

This is the base class for all rule objects. Therefore, all object rules must have all properties and methods explained here.

Properties:

Methods:

All methods returns the instance of the rule object.

You may ask why there are some set* method, why don’t leave read-write property alone. It is to make fluent interface which is more convenient. For example, when you set rule for withValidation rules option:

const Input = withValidation(..., {
    ...
    rules: [
        numeric,
        integer,
        min(0).setPriority(5),
        max(4).setMessageFunc(() => 'Too many'),
    ],
    ...
});

or in unit test:

expect(email.setValue('abc').validate().isValid).toBe(false);

Example:

An example class which you may create to validate a credit card number:

import {ValidationRule} from 'rc-validator/rules';
const validator = require("card-validator");

export class CreditCardNumber extends ValidationRule {
    contructor() {
        super();
        this.setPriority(0); //0 is default, but here if you want to set the priority
    }

    get errorMessage() {
        return this.lang('invalid credit card number');
    }

    validate() {
        this.isValid = validator.number(this.value).isValid;
        return this;
    }
}

export const ccNumber = new CreditCardNumber(); //`ccNumber` is more convienent to write than `new CreditCardNumber()`

ValidationRuleAsync

All rule objects which do validation in asynchronous mode, should inherit this class. This class has all methods and properties as owned by ValidationRule except the validate method of this class return a Promise object. For example, we have to validate a credit card number input like in ValidationRule example. But here, we have a list of valid card numbers in database. So, it must make an HTTP request to ask server to validate the number. We change validate method in the example before to be:

    async validate() {
        this.isValid = await fetch(
            `https://wwww.yourserver.com/check-cc-number?number=${encodeURIComponent(this.value)}`
        ).then(response => {
            //If card number has been registered in database, server returns HTTP status code 200 (OK)
            //If not, server returns 404 (Not Found)
            return response.ok;
        });
        return this;
    }

Built-in Rules

new StrDate(pattern, locale, isNet) or date(pattern, locale, isNet)

You can import these rules from 'rc-input-validator/rules/date'

This rule is to check the input value whether it’s a valid date value. The input value is a string. The resultValue is a Date object.
Parameters:

Property:

Method:

If you use <input type="date" /> for the date input in web app, need to know that this input will have an empty string value if the input value is invalid (not the same as the displayed value). Therefore, it will be invalidated by required rule or if not required, the input value will be valid (because of optional). To avoid this problem, follow the example below:

const rules = [new Required().setErrorMessage('Invalid date'), date(), ...];
function DateForm() {
  return <Form ...>
     ...
     <Input type="date" rules={rules}  ... />
     ...
  </Form> 
}

Required rule seems enough if you want only to check the date value is valid or not. date rule is still needed if you want to check the value using more rules, such as min or max because date rule will have resultValue as a Date object.

new Email() or email

The rule for examined the input value whether it’s a valid email address or not.

new HttpReq(uri, option) or httpReq(uri, option)

This rule will make an HTTP request to validate the value. The validation is executed in asynchronous mode.
Parameters:

The server script that handles the request made by this rule object must return a boolean value (true is valid or false is invalid) or a string of the error message. For example, if using node express, the code would look like the following one:

app.get('/check-validity', function(req, res) {
    const validity = validate(req.query.value); //suppose the function returns object: {isValid: boolean, errorMessage: string}
    let responseText;
    if (validity.isValid) responseText = JSON.stringify(true); //or just "true"
    else {
        if (validity.errorMessage) responseText = JSON.stringify(validity.errorMessage);
        else responseText = JSON.stringify(false); //or just "false"
    }
    res.send(responseText);
});

new Integer() or integer

Checks if the input value is integer or not. If the input value is a string (such as getting from TextInput) and you want it considered as number, you must also specify numeric rule for the input. The numeric rule must have higher priority (default).

new Length(minValue, maxValue) or length(minValue, maxValue) or lengthMax(maxValue)

This rule is to check a value which has length attribute such as a string or array. A number can also be checked by this rule that is to check the digit count. A value is valid if its length is not out of range. The minimum length is specified by minValue parameter and the maximum length is specified by maxValue parameter. If minValue is undefined then the minimum length is 0. If maxValue is undefined then no limit for maximum length.
Properties:

new Max(maxValue) or max(maxValue)

To limit the input value at maximum of maxValue. The data type of maxValue can be string, number or Date. If maxValue is number but the input value is string (such as getting from TextInput) then you must also specify numeric rule for the input. The numeric rule must have higher priority (default).
Property:

new Min(minValue) or min(minValue)

To limit the input value at minimum of minValue. The data type of minValue can be string, number or Date. If minValue is number but the input value is string (such as getting from TextInput) then you must also specify numeric rule for the input. The numeric rule must have higher priority (default).
Property:

new Numeric() or numeric

To assess if the input value is numeric or not.

new Regex(pattern, flags) or regex(pattern, flags)

To examine if pattern applies to the input value. pattern can be a RegExp object or a pattern string. If pattern is a string, flags parameter is the flags to add to the pattern (see this doc for more information).

new Required() or required

It’s to specify the input value cannot be empty. This rule is the highest priority, examined at the first time. If this rule is not specified then the input is optional. If optional then when the input is not filled, it’s assessed as valid, the other rules that has been specified won’t be examined.
Method:

Required.If(predicate) or required.if(predicate)

It’s the same as required rule but under a condition. The predicate parameter is a function. If it returns true then the input is required. Otherwise, it’s optional. The parameter for predicate function is the input value.

Required.If(() => false) or alwaysValid

Use this rule if you want to only use setErrorMessage method without applying any other rules.

new CustomRule(predicate, errorMessage) or rule(predicate, errorMessage)

If you need more complicated logic to assess whether the input value is valid or invalid, this rule fits for it. The predicate parameter is a function to asses the input value. The parameter of this function is the input value. The predicate function may return boolean (true is valid, false is invalid) or a string. If it returns a string then the input is considered as invalid. The returned string is the error message (by this way, you may create different error message for different condition). The errorMessage parameter is used as the error message if predicate function doesn’t return a string (returns false). If you set messageFunc then the error message will be taken from messageFunc.
Example:
The example below is the validator to check whether the number is between 5 to 9. If not then the value is invalid. If the value is not a number then it return the error message “Not valid number”. If the value less than 5 then the message is “The value is too small”. If the value is higher than 9 then the message is “The value is too big”.

rule(
    value => {
        const numb = parseFloat(value);
        if (isNaN(numb)) { //Needs more checking to ensure the `value` is really a number
            return false;
        }
        else if (numb < 5) {
            return 'The value is too small';
        }
        else if (numb > 9) {
            return 'The value is too big';
        }
        return true;
    },
    'Not valid number'
)

new CustomRuleAsync(predicate, errorMessage) or ruleAsync(predicate, errorMessage)

It is almost the same as rule rule. The difference is it runs in asynchronous mode. The predicate function for this rule doesn’t return anything. As a replacement, to set the validation status (valid/invalid or the error message), it has a second parameter which is a function. The validation status is set using this function.
Example:
As an example, we change the example for rule to be an appropriate one for ruleAsync.

ruleAsync(
    (value, resolve) => {
        const numb = parseFloat(value);
        if (isNaN(numb)) { //Needs more checking to ensure the `value` is really a number
            resolve(false);
        }
        else if (numb < 5) {
            resolve('The value is too small');
        }
        else if (numb > 9) {
            resolve('The value is too big');
        }
        else {
            resolve(true);
        }
    },
    'Not valid number'
)

new Time(pattern, locale) or time(pattern, locale)

You can import these rules from 'rc-input-validator/rules/time'

This rule is to check the input value whether it’s a valid time value. The input value is a string. The resultValue is a Date object.
Parameters:

Property:

Method:

If you use <input type="time" /> for the time input in web app, need to know that this input will have an empty string value if the input value is invalid (not the same as the displayed value). Therefore, it will be invalidated by required rule or if not required, the input value will be valid (because of optional). To avoid this problem, follow the example below:

const rules = [new Required().setErrorMessage('Invalid time'), time(), ...];
function TimeForm() {
  return <Form ...>
     ...
     <Input type="time" rules={rules}  ... />
     ...
  </Form> 
}

Required rule seems enough if you want only to check the time value is valid or not. time rule is still needed if you want to check the value using more rules, such as min or max because time rule will have resultValue as a Date object.

Built-in Rules from “web” Module

Form "rc-input-validator/web/rules" module, we can import some rules useful for the web app, especially to examine <Input type="file" />.

These rules are not exclusively for a web app. If you have an input component in a React Native app which has the value as a File object, these rules can also be applied to.

fileExt(extension)

This rule is to check whether the file has the valid extension name or not.
Parameters:

If the file input holds more than one file (because multiple attribute is set), the input is considered invalid if any file name is invalid.
NOTE: we may specifies an empty string for extension parameter that means the file name has no extension.

` fileMax(max, unit)`

This rule is to check the file size whether exceeds the maximum size.
Parameters:

If the file input holds more than one file (because multiple attribute is set), the input is considered invalid if there is a file whose size exceeds the maximum size.

` fileTotalMax(max, unit)`

This rule is to check the total size of multiple file whether exceeds the maximum size. This rule is suitable for the file input whose multiple attribute (<Input type="file" multiple />) even if it can also be applied to a single file input.
Parameters:

fileType(type)

This rule is to check whether the file has the valid MIME type or not.
Parameters:

If the file input holds more than one file (because multiple attribute is set), the input is considered invalid if any file MIME type is invalid.

new FileCheck(validateFunc, message) or fileCheck(validateFunc, message)

If four rules above are not enough, fileCheck is more flexible rule because we may define a function to validate the input. Actually, four rules above utilize this rule.
Parameters:

For example, we want to avoid too small file size or even has no content. The following rule limits the file size minimum at 1kb:

fileCheck(
    (files, calculateSize) => {
        const minSize = calculateSize({size: 1, unit: 'K'});
        for (let file of files) if (file.size < minSize) return false;
        return true;
    },
    'File size is too small'
)

Messages

Each built-in rule object has default error message. You must inspect them in the case that you want to translate them to the other languages. The messages can be found in messages.ts. The messages are listed in the following code:

{
    asyncFail: 'cannot validate',
    date: 'invalid date and/or time',
    email: 'invalid email address',
    httpReq: {
        disconnected: "Can't connect to server",
        notOk: "Server failed to process data",
        invalid: "Can't interpret server response",
    },
    integer: 'must be the round number',
    invalid: 'invalid',
    lengthMax: "Exceeds the maximum length of ${max}",
    lengthMin: 'the length must be minimum at ${min}',
    max: 'maximum ${max}',
    min: 'minimum ${min}',
    numeric: 'invalid numeric value',
    required: 'required',
    time: 'invalid time'
}

and also in web/messages.ts:

{
    fileCheck: 'invalid file',
    fileExt: 'invalid extension of the file name',
    fileMax: 'exceeds the allowed size',
    fileTotalMax: 'exceeds the allowed total size',
    fileType: 'invalid type of the file',
}

These default messages can be changed that will affect the whole app. For example, you want to change ‘required’ message to be ‘must be filled’. To do that, insert some codes into index.ts in the root directory of React Native app like the following:

    import {AppRegistry} from 'react-native';
    import App from './App';
    import {name as appName} from './app.json';

    import messages from 'rc-input-validator/messages';
    messages.required = 'must be filled';

    AppRegistry.registerComponent(appName, () => App);

The lines which have bold font are the inserted code.

If you read the message for max or min rule, you find the special words ${max} and ${min}. They are the variable placeholder that will be replaced by the real value. The error message will be processed by str function. The second parameter for the function is the examined rule object. Therefore, the variable name in the template string is the property name of the rule object. For example, in the example before, you want to display the input name in the message. You must change the second bold line to be

messages.required = '${name} must be filled';

To make it works, you must also set the input name in withValidation name option or name prop of the web input.

Example App

There is an example app you can find here