DataValidatorListener is one of the default listeners of MOST data models. Validates data objects against validation rules defined in model attributes.
Validation Rules
Each attribute may have a set of validation rules. These rules may validate data against:
Use default validation rules
In the following example price attribute has a validation which allows values between 0 to 1000:
{
"name": "price",
"title": "Price",
"description": "The price of the product.",
"type": "Number",
"nullable":false,
"validation": {
"minValue":0,
"maxValue":1000
}
}
The following code snippet tries to save an object with a negative value in price:
var obj = {
"price": -23.45,
"model": "FS2400",
"name": "USB 3.0 Adapter"
};
context.model("Product").save(obj).then(function() {
return done();
}).catch(function(err) {
return done(err);
});
and the result is:
{
"code": "ERANGE",
"model": "Product",
"field": "price",
"message": "The value should be between 0 to 1000."
}
Use data type validation
A validation may be performed by using a pre-defined data type:
{
"name": "price",
"title": "Price",
"description": "The price of the product.",
"type": "Number",
"nullable":false,
"validation": {
"type":"NonNegativeNumber"
}
}
An operation tries to save a product with a negative price:
var obj = {
"price": -23.45,
"model": "FS2400",
"name": "USB 3.0 Adapter"
};
context.model("Product").save(obj).then(function() {
return done();
}).catch(function(err) {
return done(err);
});
and the result is:
{
"code": "EPATTERN",
"model": "Product",
"field": "price",
"message": "The value should be a number greater or equal to zero."
}
The following list contains a set of pre-defined data types which may be used for data type validation:
Type | Description |
NegativeInteger | An integer containing only negative values (..,-2,-1) |
NegativeNumber | A number containing only negative values (..,-2,-1) |
NonNegativeInteger | An integer containing only non-negative values (0,1,2,..) |
NonNegativeNumber | An number containing only non-negative values (0,1,2,..) |
NonPositiveInteger | An integer containing only non-positive values (..,-2,-1,0) |
NonPositiveNumber | A number containing only non-positive values (..,-2,-1,0) |
PositiveInteger | An integer containing only positive values (1,2,..) |
PositiveNumber | A number containing only positive values (0.1,+1,2,..) |
Float | Float data type is a single-precision floating point. |
Email | A string which represents an email address (e.g. user@example.com) |
Guid | A string which represents a global unique identifier (e.g. 21EC2020-3AEA-4069-A2DD-08002B30309D). |
AbsoluteURI | A string which represents an absolute URI address (e.g. https://www.example.com/help?article=1001) |
RelativeURI | A string which represents a relative URI address (e.g. /help?article=1001) |
Time | A string which represents an instant of time that recurs every day (e.g. 13:20:45) |
Date | Represents a date value. |
DateTime | Represents a date and time value. |
Duration | A string which represents a duration of time (e.g. P1Y1M10D, P10D, -P0Y1M10D2H15M30S etc) |
IP | A string which represents an IPv4 address (e.g. 127.0.0.1) |
Value validation may be performed by custom validator which is being registered as follows:
{
"name": "price",
"title": "Price",
"description": "The price of the product.",
"type": "Number",
"nullable":false,
"validation": {
"validator":"./validators/price-validator"
}
}
where price-validator is a module which exports a createInstance() method
that returns an instance of a class which inherits DataValidator class.
//# ./validators/price-validator
var util = require("util"),
most = require("most-data");
function PriceValidator(attr) {
this.attr = attr;
PriceValidator.super_.call(this);
}
util.inherits(PriceValidator, most.validators.DataValidator);
PriceValidator.prototype.validateSync = function(val) {
if (typeof val === 'number') {
if (val<=0) {
return {
code:"EPRICE",
"message":"A valid price must be always greater than zero."
};
}
}
else {
return {
code:"EPRICE",
"message":"A valid price must be always a number greater than zero."
};
}
};
exports.createInstance = function() {
return new PriceValidator();
};
An operation tries to save a data object:
var obj = {
"price":-10.75,
"model": "FS2USB3",
"name": "USB 3.0 Adapter"
};
context.model("Product").save(obj).then(function() {
return done();
}).catch(function(err) {
return done(err);
});
and the result is:
{
"code": "EPRICE",
"model": "Product",
"field": "price",
"message": "A valid price must be always greater than zero."
}
A custom validator may use async validate(val,callback) method:
PriceValidator.prototype.validate = function(val, callback) {
this.getContext().model("Product")
.where("price").lowerThan(val).count()
.then(function(result) {
if (result<=5) {
return callback(null, {
code:"EPRICE",
"message":util.format("You have already 5 products with price lower than %s.", val)
});
}
return callback();
}).catch(function(err) {
return callback(err);
});
};
and the result may be:
{
"code": "EPRICE",
"model": "Product",
"field": "price",
"message": "You have already 5 products with price lower than 10."
}