Skip to content

User Contributed Rules

joshthang edited this page Nov 15, 2012 · 20 revisions

###Please feel free to contribute your own Custom Rules!###

####Example Rule####

ko.validation.rules['exampleRule'] = {
    validator: function(val, otherVal){
        /* awesome logic */
    },
    message: 'Sorry Chief, {0} this is not Valid'
};

####Requires one of more (in array)####

/*
 * This rules checks the given array of objects/observables and returns 
 * true if at least one of the elements validates agains the the default
 * 'required' rules
 * 
 * Example:
 * 
 *
 * self.mobilePhone.extend({ requiresOneOf: [self.homePhone, self.mobilePhone] });
 * self.homePhone.extend({ requiresOneOf: [self.homePhone, self.mobilePhone] }); 
 *
*/

ko.validation.rules['requiresOneOf'] = {
  getValue: function (o) {
    return (typeof o === 'function' ? o() : o);
  },
  validator: function (val, fields) {
    var self = this;

    var anyOne = ko.utils.arrayFirst(fields, function (field) {
      var stringTrimRegEx = /^\s+|\s+$/g,
                testVal;

      var val = self.getValue(field);

      if (val === undefined || val === null) 
        return !required;
      
      testVal = val;
      if (typeof (val) == "string") {
        testVal = val.replace(stringTrimRegEx, '');
      }

      return ((testVal + '').length > 0);

    });

    return (anyOne != null);
  },
  message: 'One of these fields is required'

};

####Change Limit Rule####

/**
 * Limits the maximum amount a numeric value can be changed.
 * Parameters: maxChange: <The max valid value change from base value>,
 *             baseValueAccessor: <A function to access the base value>
 * 
 * Example: 'Distance can change a maximum of 10'
 * var initDistance = 5;
 * this.distance.extend({
 *     changeLimit:{
 *         maxChange:10,
 *         baseValueAccessor:function () {
 *             return initDistance;
 *         }
 *     }
 * });
 * 
 */
ko.validation.rules['changeLimit'] = {
    validator: function(val, options) {
        return Math.abs(val - options.baseValueAccessor()) <= options.maxChange;
    },
    message: 'Change limit exeeded'
};

####Valid Object####

/*
 * Aggregate validation of all the validated properties within an object
 * Parameter: true|false
 * Example:
 *
 * viewModel = {
 *    person: ko.observable({
 *       name: ko.observable().extend({ required: true }),
 *       age: ko.observable().extend({ min: 0, max: 120 })
 *    }.extend({ validObject: true })
 * }   
*/
ko.validation.rules["validObject"] = {
    validator: function (obj, bool) {
        if (!obj || typeof obj !== "object") {
            throw "[validObject] Parameter must be an object";
        }
        return bool === (ko.validation.group(obj)().length === 0);
    },
    message: "Every property of the object must validate to '{0}'"
};

####Valid Array####

/*
 * Aggregate validation of all the validated elements within an array
 * Parameter: true|false
 * Example
 *
 * viewModel = {
 *    person: ko.observableArray([{
 *       name: ko.observable().extend({ required: true }),
 *       age: ko.observable().extend({ min: 0, max: 120 })
 *    }, {
 *       name: ko.observable().extend({ required: true }),
 *       age: ko.observable().extend({ min:0, max:120 })
 *    }].extend({ validArray: true })
 * }   
*/
ko.validation.rules["validArray"] = {
    validator: function (arr, bool) {
        if (!arr || typeof arr !== "object" || !(arr instanceof Array)) {
            throw "[validArray] Parameter must be an array";
        }
        return bool === (arr.filter(function (element) {
            return ko.validation.group(ko.utils.unwrapObservable(element))().length !== 0;
        }).length === 0);
    },
    message: "Every element in the array must validate to '{0}'"
};

####htmlNotEmpty####

ko.validation.rules['htmlNotEmpty'] = {
    validator: function (val, otherVal) {
    
        function isBlank(str) {
            return (!str || !str.match(/\S/));
        }

        function isEmpty(str) {
            return (!str || 0 === str.length);
        }
        
        function isHtmlEmpty(str) {
            if (!str.match(/^\s*?\\</)) return false;
            var s = $(str).text();
            return (isEmpty(s) || isBlank(s));
        }
    
        var invalid = isEmpty(val);
        if (!invalid) invalid = isHtmlEmpty(val);

        return !invalid;
    },
    message: 'Invalid.  Please enter a value'
};

####Nullable Integer####

ko.validation.rules['nullableInt'] = {
    validator: function (val, validate) {
        return val === null || val === "" || (validate && /^-?\d*$/.test(val.toString()));
    },
    message: 'Must be empty or an integer value'
};

####Nullable Decimal####

ko.validation.rules['nullableDecimal'] = {
    validator: function (val, validate) {
        return val === null || val === "" || (validate && /^-?\d*(?:\.\d*)?$/.test(val.toString()));
    },
    message: 'Must be empty or a decimal value'
};

####Conditional Required####

/*
 * Determines if a field is required or not based on a function or value
 * Parameter: boolean function, or boolean value
 * Example
 *
 * viewModel = {
 *   var vm = this;
 *   vm.isRequired = ko.observable(false);
 *   vm.requiredField = ko.observable().extend({ conditional_required: vm.isRequired});
 * }   
*/
ko.validation.rules['conditional_required'] = {
    validator: function (val, condition) {
        var required = false;
        if (typeof condition == 'function') {
            required = condition();
        }
        else {
            required = condition;
        }

        if (required) {
            return !(val == undefined || val == null || val.length == 0);
        }
        else {
            return true;
        }
    },
    message: "Field is required"
}
Clone this wiki locally