More than just an object validator.
Creating powerful validators is very easy with OVP.
// having initialized OVP
ovp.addValidator(name, validationFn, error);
Argument | Description |
---|---|
name |
Name of the validator e.g: min or max etc… |
validationFn |
Function to handle validation. |
error |
Error Message. |
The error
message can parse two keywords if found.
:param
: The key of the object being validated.
:option
: The option passed to the validator in the rules object.
Your validationFn
must return true
or false
and receives 3 arguments on validation. e.g
Argument | Description |
---|---|
val |
Value of the key in the object being validated. |
opt |
Option passed in the rule. |
obj |
An ObjectOnValidation class to modify the current object being validated |
// First we create a validator named: MyValidator
ovp.addValidator('myValidator', (...args) => {
console.log(args);
return false;
}, ':param failed myValidator');
The above syntax creates a validator named myValidator
and logs all the arguments it receives.
Now lets run some validation to see how this turns out.
// An object to validate
let ourObject = {
hobbies: ['eat', 'code', 'sleep'],
website: {
name: 'My Website',
url: 'some-blog-in-3030.com'
}
};
// Rules to validate with
let rule = {
hobbies: {myValidator: 'any'}
};
// Run Validation
let isValid = ovp.validate(ourObject, rule);
console.log(isValid);
// logs
[[ 'eat', 'code', 'sleep' ], 'any', ObjectOnValidation]
[ 'hobbies', 'Hobbies failed myValidator' ]
false
The log above explains that val
argument in validationFn
is the value of the key in the object we are validating i.e ourObject.hobbies
.
opt
is the value passed to myValidator
rule i.e ‘any’, while obj
is a helper class to modify the object we are validating.
Lets a create validator that checks if ourObject.hobbies
has an item “drink” and another validator that checks if ourObject.website.url
has “http://”
ovp.addValidator('NoDrinkInHobbies', (hobbies) => {
if(hobbies.indexOf('drink') >= 0) {
return false;
}
}, 'Drink found in :param');
ovp.addValidator('hasHttp', (url) => {
if(url.substr(0, 7) !== 'http://'){
return false;
}
}, ':param must start with http://');
// new rule
let rule = {
hobbies: {NoDrinkInHobbies: true},
'website.url': {hasHttp: true}
};
// Run Validation
isValid = ovp.validate(ourObject, rule);
console.log(isValid);
// Assuming...
ourObject.hobbies = ['eat', 'code', 'sleep', 'drink'];
// Rerun Validation
isValid = ovp.validate(ourObject, rule);
console.log(isValid);
// Before Assumption
[ 'website.url', 'Website Url must start with http://' ]
false
// After Assumption
[ 'hobbies', 'Drink found in Hobbies' ]
false
In the first validation, website.url
fails because hasHttp
validator returned false
.
After changing the value of ourObject.hobbies
the second validation fails because NoDrinkInHobbies
returned false.
Sometimes not all validations requires program halt, some validations are for fixing things.
e.g Instead of stopping the above process because website.url
does not have “http://”, why don’t we add it ourselves?
// lets add a different validator
ovp.addValidator('addProtocol', (url, protocol, obj) => {
protocol = protocol + '://';
if (url.substr(0, protocol.length) !== protocol){
obj.setThis(protocol + url);
}
});
ovp.validate(ourObject, {
'website.url': { addProtocol: 'ftp' }
});
console.log(ourObject.website.url);
// logs: ftp://some-blog-in-3030.com
// Rerun with http instead
ovp.validate(ourObject, {
'website.url': { addProtocol: 'http' }
});
console.log(ourObject.website.url);
// logs: http://some-blog-in-3030.com
Notice our new validator does not have an error? this is because we know this has no errors.
obj.setThis
? this is a function in the ObjectOnValidation
Class. .setThis
sets the value of the current key we are validating.
i.e
// this line
obj.setThis(protocol + url);
// is equivalent to
ourObject.website.url = protocol+url;
// can also be set like this
obj.set('website.url', protocol+url);
// any key of the obj can be modified or created using
obj.set(path, value);
Do see the ObjectOnValidation
Class. It provides great helpers that assists with current object on validation modification.
Ovp handles async validators using the validateAsync
function.
validatorFn
must also have async
before it to be treated as async.
All async validators are waited for and a Promise<boolean>
is returned to you.
Lets check if website.url
is a valid url using axios
.
const axios = require('axios');
// lets add urlIsOnline Async validator.
ovp.addValidator('urlIsOnline', async (value) => {
try{
await axios.get(value);
return true;
}catch(e){
return false;
}
}, 'Url is not online!');
let asyncTestData: {
url: 'some-blog-in-3030.com'
};
let asyncRule = {
'url': {addProtocol: 'https', 'urlIsOnline': true}
};
ovp.validateAsync(asyncTestData, asyncRule).then((isValid) => {
// isValid is false;
});
// if you are in an async function you can use await instead
let isValid = await ovp.validateAsync(asyncTestData, asyncRule);
// isValid is false;
UrlIsOnline
returned false because at the time of this documentation https://some-blog-in-3030.com is not online.
You should change the url to “google.com” and urlIsOnline
will return true
.
You can set more than one custom validator using the ovp.addBulk(arrayOfValidators)
ovp.makeValidator()
: returns the object data of a validator, works just like the new Validator
function but returns the validators data instead of setting them.
See example below to see how it works.
// Using ovp.makeValidator method
let emailValidator = ovp.makeValidator('isEmail', (email) => {
return (typeof email === "string" && email.length>5 && email.includes('@'));
}, ':param does not look like an email');
let arrayOfValidators = [
// Using Object Method
{
name: 'exact',
error: ':param is not what we are expecting!',
validator: (value, option) => {
return value === option;
}
},
// Using Object Method
{
name: 'strongPassword',
error: ':param is not strong. no Capital letter found!',
validator: (value) => {
return value.toLowerCase() !== value;
}
},
// Using ovp.makeValidator method Object from above
emailValidator,
];
console.log(arrayOfValidators);
/*
returns: =====>
[ { name: 'exact',
error: ':param is not what we are expecting!',
validator: [Function: validator] },
{ name: 'strongPassword',
error: ':param is not strong. no Capital letter found!',
validator: [Function: validator] },
{ name: 'isEmail',
error: ':param does not look like an email',
validator: [Function] } ]
*/
ovp.addBulk(arrayOfValidators);
The data return by emailValidator
in the console results is the same with the Objects manually declared in arrayOfValidators
So you can populate arrayOfValidators
any which way you find preferable.
Lets say for some reason you want to overwrite a validator that has been defined somewhere or somehow.
You can simply create a new validator with new validator function and error but same name. like below.
// Old validator.
ovp.addValidator('checkName', () => {
return true;
}, '1st Error message.');
// Overwrite using this.
ovp.addValidator('checkName', () => {
return false;
}, 'Overwritten Error message.');
The above will work perfectly but OVP also includes an easy method to modify validators.
using ovp.addValidator(name)
with only name as argument enables modification or creation using .save()
// Modify only validationFn
ovp.addValidator('checkName').validator(() => {
return true;
}).save();
// Modify only error
ovp.addValidator('checkName').error('New Error Message.').save();
You can use any style you feel comfortable with.