rulebased-validator

Rule based validator

Rule Based Validator


Rule based validator is a generic rule processing engine. Validation rules are defined using JSON syntax in a declarative way. It support most basic validation out of the box, other major supported features included in this release are:

  • Works both in browsers and in NodeJS
  • Supports both data model and field validation
  • Supports conditional validation based on other properties from the same model
  • Supports nested rules
  • Supports content validation on both arrays of strings and arrays of objects
  • Error messages can be specified at field level or at rule level.
    NOTE: A generic error message will be displayed by default
  • Custom validation function can be hooked for complicated validation logic
  • Also support the concept of excluding and including validation rule(s) in scenarios like saving a draft versus submitting a form, etc.
  • Supports stop on first error feature

In NodeJs add following require directive:

var validator = require('rulebased-validator');

In browser add following script tag:

<script src="rulebased-validator.js"></script>

and start using validator, using ruleBasedValidator variable.

NOTE:

All these examples are written in nodeJs and assumes validator module is included via require directive as per Usage section above.

var yourModelData = {
    Name: 'TestName',
    Description: 'Some notes',
    Emails: ['primary@test.com', 'secondary@test.com'],
    Phones: [{Phone: '111-222-3333', isCell: true}, 
             {Phone: '222-333-4444', isCell: false}],
    hasWebSite: true,
    Site: 'Test@test.com',
    ZipCode: '75052',
    City: 'abcd'
};

var phoneRules = {
    Phone: {
        required: true,
        isUSPhoneNumber: { 
            value: true, 
            message: 'Phone number is invalid.' 
        }
    },
    isCell: {
        required: true,
        isBool: true
    }
};

var validationRules = {
    Name: {
        required: true,
        maxLength: { 
            value: 10, 
            // rule level error message example
            message: 'Maximum of 10 characters are allowed.' 
        }
    },
    Description: {
        required: false, // same as not specifying this rule
        maxLength: 10,
        // property level error message example
        message: 'Description is optional, if specified should not              exceed 10 characters.'
    },
    City: {
        // this is an example of conditionally apply validation rule 
        // only on submit
        required: { 
            value: true, 
            message: 'City is required on submit, but not on save as                  draft.', 
            group: ['submit'] 
        }
    },
    ZipCode: {
        required : true,
        isUSZipCode: { value: true, message: 'Zip code is invalid.' },
        inList: ['75052', '75053'],
        message : 'Valid zipcode is required.'
    },
    Emails: {
        isArray: true,
        minLength: 1,
        maxLength: 3,
        contentRules: { isEmail: true }
    },
    Phones: {
        isArray: true,
        minLength: 1,
        maxLength: 3,
        contentRules: phoneRules,
        // example of using content rule for phone object validation
        message: 'Invalid phone entries.'
    },
    hasWebSite: {
        required: true,
        isBool: true
    },
    Site: {
        dependsOn: {
            propName: 'hasWebSite',
            propValue: 'true',
            rules: { 
                isUrl: { 
                    value: true, 
                    message: 'Site url is invalid.' 
                }
            }           
        }
    }
};

// to do model validation, use following:
var result = validator.validate(yourModelData, validationRules);
// or like this: var result = validator.validate(yourModelData, validationRules, 'submit'); // last parameter is rule's group name
if (result === true)
    console.write('No validation errors.');
else { // else validation errors
    // errors will be returned as and array of error object 
    if (result != null) {
        foreach (var err in result) {
            console.write('Field Name: ' + err.fieldName);
            console.write('Field Value: ' + err.fieldValue);
            console.write('Rule Name: ' + err.ruleName);
            console.write('Error Message: ' + err.errorMessage);
        }
    }
}

Using the above example rules and data, field can be validated like this:

// param1: property name
// param2: value of the property
// param3: validation rule for the property
var result = validator.validateField('Phones', yourModalData.Phones, validationRules.Phones);

if validating a field that depends upon some other property then also pass the entire model as follows:

// param1: property name
// param2: value of the property
// param3: validation rule for the property
// param4: entire data model
var result = validator.validateField('Site', yourModalData.Site, validationRules.Site, yourModalData);

if validation rule is defined for 'submit', then pass group name as additional parameter.

In this case rule will be applied only if a group match is found. Field validation rule will be invoked like this:

// param1: property name
// param2: value of the property
// param3: validation rule for the property
// param4: entire data model
// param5: group name
var result = validator.validateField('City', yourModalData.City, validationRules.City, yourModalData, 'submit');

NOTE:

  • when group name is not supplied, rule will be applied.
  • when group name is supplied but not in the rule group list, rule will be ignored
  • when group name is supplied and found in the rule group list, rule will be applied

NOTE: Hierarchy is indicated by "_" by default. But this character can be modified by setting hierarchyIndicator property on ruleBasedValidator, as shown below:

validator.hierarchyIndicator = '#';

This will set hierarchy indicator to "#" character. Here is the sample for the nested rules.

var nestedSampleRules = {
    Name: { required: true },
    Contact: { required: true },
    Contact_Name: { required: true },
    Contact_Name_First: { required: true, maxLength: 10 },
    Contact_Name_Last: { maxLength: 10 },
    Contact_Email: { required: true }
}; 

var nestedSampleData = {
    Name: 'Test',
    Contact: {
        Name: {
            First: 'first',
            Last: 'last'
        },
        Email: 'sample@test.com'
    }
};

to do modal validation, use the following:

var result = validator.validate(nestedSampleData, nestedSampleRules);
if (result === true)
    console.write('No validation errors.');
else { // else validation errors
    // errors will be returned as and array of error object 
    if (result != null) {
        foreach (var err in result) {
            console.write('Field Name: ' + err.fieldName);
            console.write('Field Value: ' + err.fieldValue);
            console.write('Rule Name: ' + err.ruleName);
            console.write('Error Message: ' + err.errorMessage);
        }
    }
}

This is how stop on first error can be enabled:

validator.stopOnFirstError = true;  // when set to true, validation will stop at first validation error

This is how stop on first error can be disabled:

validator.stopOnFirstError = false;  // when set to false, all validation rules will be applied irrespective of failure or success of each individual rule