react-native-form-input-validator
v1.3.1
Published
Doing validation to form inputs in React Native app
Downloads
8
Maintainers
Readme
react-native-form-input-validator
It's to validate the input's value in RN app such as TextInput
or other kind of inputs. The value is validated based on the rule defined for the input.
If the input is invalid, the error message is shown beneath the input. It's very useful before submitted to the server. See the pictures below for some
examples.
More fancy example which uses an icon to reflect the validation status:
A Brief Example
import React from 'react';
import {
Button,
StyleSheet,
Text,
TextInput,
View,
} from 'react-native';
import {
setStatusStyleDefault,
ValidationContext,
withValidation,
} from "react-native-form-input-validator";
import {
email,
required,
} from 'react-native-form-input-validator/rules';
import server from './server';
const UserName = withValidation(TextInput, {
rules: [email, required],
setStatusStyle: setStatusStyleDefault,
});
const Password = withValidation(TextInput, {
rules: required,
setStatusStyle: setStatusStyleDefault,
});
export default function LoginForm() {
const validationRef = React.useRef();
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,
},
});
API Reference
You have seen the example above. 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 input at once.
ValidationContext
This element can validate all contained inputs in it that have been set by withValidation
. Also, it can
clear the validation status of those inputs. You may treat this element like form
tag in HTML document. Some properties that can be set
for this element are:
Methods and property of ValidationContext
reference (the object that we get from ref
property):
clearValidation
It executesclearValidation
method of all contained inputs to clear the validation status of all contained inputs.isValid
is the property to check the validity status of all inputs inside the context. If there is an invalid input, this property will havefalse
value. Otherwise it'strue
. The value of this property is trusted after callingvalidate
orvalidateAsync
.getErrorMessage(name)
returns the error message that is being displayed for the input whose the name specified byname
parameter and inside the currentValidationContext
. It returns an empty string if no error message displayed for that input. It returnsundefined
if no input whose suchname
.getInput(name)
returns the reference of the input whose the name specified byname
parameter and inside the currentValidationContext
. It returnsundefined
if no input whose suchname
.refreshMessage
For a multi languange app, this method is useful to update the language of the error messages. This methods will re-validate all contained inputs so that their error messages are refreshed. Because of that, if the input is already valid then the error message will be gone.setErrorMessage(name, message)
This method is to set error message for an input whose the name specified byname
parameter.message
parameter is the error message to show. The input must be inside the currentValidationContext
. This method is useful when dealing with server-side validation.validate
It executesvalidate
method of all contained inputs to validate all contained inputs. This method returnsfalse
if any invalid input and returnstrue
otherwise.validateAsync
It executesvalidateAsync
method of all contained inputs to validate all contained inputs. This method returns aPromise
object that will resolve tofalse
if any invalid input ortrue
if otherwise.
withValidation
This function is to create 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 properties which specify validation rules and the other attributes. But if you only need to set the validation rule(s) for the input, the second parameter can a rule object or an array of rule objects.
I think the example above is enough to depict how to use this function. So, in this section, we will
discuss the option properties more detailedly. The only property you must specify is rules
.
Methods and properties of the input reference (the object that we get from ref
property):
clearValidation
It's to clear validation status. The error message will disappear and the input style is reverted to normal. After executing this method,isValid
will be reset totrue
even if the input is invalid. Ifauto
validation is disabled, this method will be called when the user changes the input value right after the validation.getErrorMessage
This method returns the error message being displayed for the input. It returns an empty string if no error.isValid
It shows the validity status of input. It'strue
if valid andfalse
if invalid. The value of this property is trusted after callingvalidate
orvalidateAsync
.name
It's the name of input. The value of this property is the same as that specified forname
option.setErrorMessage(message)
This method can set the error message for the input without callingvalidate
orvalidateAsync
. It won't validate any rule that has been applied to the input. By calling this method, the input status becomes invalid (isValid
property isfalse
).For example, we need to validate the input on the server because we must read the database to make sure the inputed user name is unique. (NOTE: The example below should be solved using asynchronous validation interfaces).
const validateAsync = () => new Promise((resolve, reject) => { fetch( `https://yourserver.com/validate/unique-user-name?uname=${encodeURIComponent(userName)}` ).then(async (response) => { if (response.ok) return response.json(); reject(await response.text()); }).then(data => { if (data.userNameExists) { userNameInput.current?.setErrorMessage('The user name has been used'); resolve(false); } else { resolve(true); } }).catch(err => { reject(err); }); }) .catch(err => { /*If there is a problem with the server, you may tell the user here or you may just keep it silent and try to re-validate it on the server when the form is submitted. In fact, backend validation is still needed all time to avoid tampered data.*/ //userNameInput.current?.setErrorMessage('The server cannot validate'); }); <UserNameInput ref={userNameInput} onBlur={validateAsync} onChangeText={setUserName} value={userName} />
Another example, when the validation process yields an error:
<UserNameInput ref={userNameInput} onChangeText={setUserName} value={userName} onBlur={() => { try { userNameInput.current.validate(); } catch { userNameInput.current.setErrorMessage('An error happens when validating'); } }} />
Need to remember that
rules
option is required. If you want to usesetErrorMessage
method but doesn't need to apply any validation rule, you can usealwaysValid
rule.validate
This method is to validate the input based on the specified rules. Below is the example how to validate input when it's lost focus.<NameTextInput ref={nameInput} onBlur={() => nameInput.current?.validate()} onChangeText={setName} value={name} />
This method returns
true
if input value is valid orfalse
if invalid. This method will throw an error if there is a rule object which does the asynchronous validation.validateAsync
Asvalidate
, this method is also to validate the input based on the specified rules but the process is executed in asynchronous mode. This method returns aPromise
object that will resolve totrue
if the input value is valid orfalse
if otherwise.
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();
}} ... />
Style Handling
To make the input and the error message stick together, withValidation
wraps them into a View
container. 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 a View
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 View
container. Therefore, the component yielded by
withValidation
will move all style attributes dealing with layout to be the style attributes of View
container. Then, the input must be set to fill the area of View
container.
We know, the value for style property is not always 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 View
container:
alignSelf
bottom
display
end
flexGrow
flexShrink
flexBasis
left
margin
marginBottom
marginEnd
marginHorizontal
marginLeft
marginRight
marginStart
marginTop
marginVertical
maxWidth
minWidth
position
right
start
top
transform
width
zIndex
Some other attributes will be moved to View
containner under a condition:
height
,minHeight
andmaxHeight
, if having the percentage valueflex
, if greater than 0.
To make sure the input fill the area of View
container, its flex
attribute is set to 1 if the View
container has one of
attributes: height
(percentage), flex
or flexBasis
. But if 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 View
container) lays its children horizontally (flexDirection
is row
). To
avoid it, you should set the 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={{borderWidth: 1, ...}} ... />
//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,
]} ... />
...
);
}
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
. 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
react-native-form-input-validator
pakcage is to validate inputs in React Native app. 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 are 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
are 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(this.state),
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) {
this.contextRef.current.setErrorMessage(inputName, errors[inputName]);
}
if (this.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 react-native-form-input-validator
pakcage. However, you must import the rule objects and the needed fuctions
from "dist" directory. For example:
const {
validate
} = require("react-native-form-input-validator/dist/helpers");
const {
required,
rule,
strlen,
} = require('react-native-form-input-validator/dist/rules');
To validate an input, follow the example below:
const passwordRules = [
required,
strlen(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.
Validation
Component
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:
style
is the style forView
container rendered byValidation
component. See Style Handling section, which style attributes that have effect.value
is the validated value. It can be an actual value or a function. If it's a function then the function will be executed to get the real value. The fuction is useful to create a dynamic value.
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 "react-native-form-input-validator";
import {email, required} from 'react-native-form-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
.
Functions
The functions here can be imported from the package.
setStatusStyleDefault
This function is intended to be assigned to withValidation
setStatusStyle
option. This
function executes the common statements to set input style. Here is the source code which may inspire you to make your own.
function setStatusStyleDefault(props, style) {
/**
* Need to remember: the input's style property has been flattened by `withValidation` function. So, normally,
* it can't be an array.
*/
let inputStyle = getStyleDefault(props);
if (style) { //The input style needs to change
if (Array.isArray(inputStyle)) {
//The input has got the error/success style. Don't be double set so that it can be reverted to normal style easily
if (style !== inputStyle[1]) {
setStyleDefault(props, [inputStyle[0], style]);
}
}
else {
setStyleDefault(props, [inputStyle, style]);
}
}
else //back to normal style
if (Array.isArray(inputStyle)) {
setStyleDefault(props, inputStyle[0]);
}
}
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
. All rule objects are imported from
'react-native-form-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:
errorMessage
Read-only. The error message if the input is invalid. If you define a new rule class, you should override this property to return the default error message. The value of this property can be a template string that can include some properties of the defined rule object. For example:"${name} is invalid. ${value} is not valid phone number"
.isValid
It'strue
if valid andfalse
if invalid. It's set byvalidate
method. Therefore, it's trusted just after callingvalidate
method.lang
is a function to translate the error message to the active languange. By default, the message is in english. It will be set byvalidate
method of input ref that will be the same as contextlang
orwidthValidation
lang
option.messageFunc
Read-only. It's a function which returns the error message. This error message overwrites the default message specified byerrorMessage
. The parameter of the function is the rule object itself. To set this property, usesetMessageFunc
method.name
is the name of validated input. It's set byvalidate
method of input ref which is the same aswidthValidation
name
option.priority
Read-only. If we specify some rules to validate the input,priority
determines which rule to be examined first.priority
has a number value. The lower value means the higher priority. By existence ofpriority
, you don't need to bother the order inrules
array ofwithValidation
option. The value of this property is set bysetPriority
.By default, the built-in rules have the priority as following (ordered based on which is examined first):
required
,required.if
(the priority cannot be changed, always the highest)email
,numeric
,strlen
,strlenmax
integer
max
,min
regex
rule
httpReq
,ruleAsync
If two rules have the same priority, the order in the
rules
array determines which one first.value
is the input value that is validated. It's set byvalidate
method of input ref.resultValue
After callingvalidate
,resultValue
will save a value with valid data type. For example, fornumeric
rule, it will save a number value, not string likevalue
. By default, it's the same asvalue
(with the same data type).
Methods:
setMessageFunc
is to setmessageFunc
property.setName
is to setname
propety.setPriority
is to setpriority
. You should set a non-negative number.setValue
is to setvalue
property.validate
is to validatevalue
and then setisValid
based on the validity ofvalue
.
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 'react-native-form-input-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;
}
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:
uri
is the URI string for HTTP request. This parameter is required.option
defines the settings for HTTP request. This parameter is optional.option
is a plain object whose one or more properties listed below (all properties are optional):data
is request data that will be sent to server.data
can be a plain object or aURLSearchParams
object. Ifdata
is set then the request will use POST method.name
andvalue
will be automatically included indata
(you doesn't need to set them indata
).
Ifdata
is not set then the request will use GET method.name
andvalue
will be inserted into URI string as the query part. If you want to use POST method but have no data other thanname
andvalue
, setdata
as an empty object ({}
) or asnew URLSearchParams()
without setting any data.headers
is a plain object contains request HTTP headers. The keys of object are the header names and their values are their corresponding header values. For example:httpReq( 'https://www.yourserver.com/checkdata', { headers: { { Authorization: `Bearer ${publicKey}` }, {'X-Requested-With': 'MyApp'} } } )
silentOnFailure
if it'strue
then there won't be any error message if a problem happens to the server response. The problems that can happen are timeout, response code is not ok etc. The input value is also considered valid. You must revalidate the input value on the server. In fact, backend validation on the server is still needed all time to avoid tampered data. By default,silentOnFailure
isfalse
(there will be an error message if a problem happens).timeout
defines the connection timeout in milliseconds. The default value is 0 (no timeout).
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 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:
max
is the maximum value (the same asmaxValue
parameter of contructor)
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:
min
is the minimum value (the same asminValue
parameter of contructor)
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.
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 approprite 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 StrLength(minValue, maxValue)
or strlen(minValue, maxValue)
or strlenmax(maxValue)
After the input value is converted to string, this rule is to limit the length of the value string. 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:
max
is the maximum length (the same asmaxValue
parameter of contructor)min
is the minimum length (the same asminValue
parameter of contructor)
Messages
Each built-in rule object has default error message. All messages are collected in one object. You must
inspect them in the case that you want to translate them to the other languages. The messages can be found in messages.js
. The
messages are listed in the following code:
{
asyncFail: 'cannot validate',
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',
max: 'maximum ${max}',
min: 'minimum ${min}',
numeric: 'invalid numeric value',
required: 'required',
strlenmax: "don't exceed ${max} characters",
strlenmin: 'must be at least ${min} characters',
}
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.js
in the root directory of app like the following:
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.
Example App
There is an example app you can find here